2015-01-05 57 views
26

我有以下代碼爲我的紋波:如何在Android 5.0 Lollipop的代碼(不是xml)中以編程方式使用RippleDrawable?

<?xml version="1.0" encoding="utf-8"?> 
<ripple xmlns:android="http://schemas.android.com/apk/res/android" 
    android:color="?android:colorControlHighlight"> 
    <item android:id="@+id/rip"> 

     <shape android:shape="oval"> 
      <solid android:color="?android:colorAccent"/> 
     </shape> 
    </item> 
</ripple> 

現在我想給用戶選擇自己的顏色的可能性,所以我需要以編程方式創建的紋波。
我發現this,我認爲這是正確的做法,但我不知道如何處理。

的波動將在這裏使用:

<ImageButton 
    android:id="@+id/add_button" 
    android:layout_width="@dimen/diameter" 
    android:layout_height="@dimen/diameter" 
    android:layout_gravity="end|bottom" 
    android:layout_marginBottom="@dimen/add_button_margin" 
    android:layout_marginEnd="@dimen/add_button_margin" 
    android:layout_alignParentBottom="true" 
    android:layout_alignParentEnd="true" 
    android:src="@drawable/ic_action_add_person" 
    android:tint="@android:color/white" 
    android:background="@drawable/oval_ripple" 
    android:elevation="@dimen/elevation_low" 
    android:stateListAnimator="@anim/button_elevation" 
    android:contentDescription="Neuer Spieler" /> 

我需要的背景設置爲RippleDrawable這樣的:

addButton.setBackground(ripple); 
+0

你在哪裏使用你的XML資源? – pskink

+0

@pskink我編輯了第一篇文章:) – ich5003

+0

所以最新的問題與創建一個新的'RippleDrawable'? – pskink

回答

44

這是我如何能夠實現這一目標。

請注意,這是Api 21+,因此如果您支持較低版本,則必須回退到普通Drawable。

public static RippleDrawable getPressedColorRippleDrawable(int normalColor, int pressedColor) 
{ 
    return new RippleDrawable(getPressedColorSelector(normalColor, pressedColor), getColorDrawableFromColor(normalColor), null); 
} 

public static ColorStateList getPressedColorSelector(int normalColor, int pressedColor) 
{ 
    return new ColorStateList(
     new int[][] 
      { 
       new int[]{android.R.attr.state_pressed}, 
       new int[]{android.R.attr.state_focused}, 
       new int[]{android.R.attr.state_activated}, 
       new int[]{} 
      }, 
     new int[] 
      { 
       pressedColor, 
       pressedColor, 
       pressedColor, 
       normalColor 
      } 
    ); 
} 

public static ColorDrawable getColorDrawableFromColor(int color) 
{ 
    return new ColorDrawable(color); 
} 

編輯: 我修修補補這個多一些,並發現ColorStateList不需要幾乎和上述方案一樣複雜。我已將其簡化爲以下代碼片段。 (上述代碼塊中的其他所有內容都是相同的,我只是改變了ColorStateList的創建。)我將把上面的代碼塊作爲原始代碼,以防萬一這個方法不適用於某人。

new ColorStateList(
    new int[][] 
     { 
      new int[]{} 
     }, 
    new int[] 
     { 
      pressedColor 
     } 
); 
+5

謝謝你很多回答:) (不能給你一個upvote,沒有足夠的聲譽)。 – ich5003

+0

當然可以;這是一個痛苦的想法,所以我很樂意分享。 :)它對你有用嗎?我對它進行了更多的修飾,並且知道我可以極大地簡化ColorStateList並獲得相同的結果,因此我編輯了我的答案以包含它。 – kdenney

+9

你也可以使用'ColorStateList.valueOf(rippleColor);' – milosmns

19
public static Drawable getAdaptiveRippleDrawable(
    int normalColor, int pressedColor) { 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
     return new RippleDrawable(ColorStateList.valueOf(pressedColor), 
       null, getRippleMask(normalColor)); 
    } else { 
     return getStateListDrawable(normalColor, pressedColor); 
    } 
} 

private static Drawable getRippleMask(int color) { 
    float[] outerRadii = new float[8]; 
    // 3 is radius of final ripple, 
    // instead of 3 you can give required final radius 
    Arrays.fill(outerRadii, 3); 

    RoundRectShape r = new RoundRectShape(outerRadii, null, null); 
    ShapeDrawable shapeDrawable = new ShapeDrawable(r); 
    shapeDrawable.getPaint().setColor(color); 
    return shapeDrawable; 
} 

public static StateListDrawable getStateListDrawable(
    int normalColor, int pressedColor) { 
    StateListDrawable states = new StateListDrawable(); 
    states.addState(new int[]{android.R.attr.state_pressed}, 
     new ColorDrawable(pressedColor)); 
    states.addState(new int[]{android.R.attr.state_focused}, 
     new ColorDrawable(pressedColor)); 
    states.addState(new int[]{android.R.attr.state_activated}, 
     new ColorDrawable(pressedColor)); 
    states.addState(new int[]{}, 
     new ColorDrawable(normalColor)); 
    return states; 
} 

你可以得到的繪製,並適用於使用view.setDrawable任何觀點。
對於棒棒糖+設備,你會得到漣漪,否則它會改變視圖的顏色。

+0

這很好。我認爲一個缺點是它可能會在應用於棒棒糖前設備時丟失圓角,因爲'StateListDrawable'中的ColorDrawable沒有形狀。 我們可以提供彩色的'ShapeDrawable'來保持形狀。但也許這會開始變得有點沉重。在這種情況下,另一種解決方案是使用「setColor」方法創建自定義「ColorStateDrawable」,從而避免您重新實例化StateListDrawable所需的所有對象。 – John

+0

在這裏找到一些東西:https://github.com/gabrielemariotti/colorpickercollection/blob/master/ColorPicker/src/it/gmariotti/android/example/colorpicker/calendarstock/ColorStateDrawable.java – John

2

基本上,您需要創建一個新的RippleDrawable對象。對於預棒棒糖設備,您需要一個StateListDrawable(如其他人已經提出的那樣)。我寫了一個有些足智多謀的GIST有一堆有關可繪製和着色有用的方法: https://gist.github.com/milosmns/6566ca9e3b756d922aa5

,您很可能希望使用#getBackgroundDrawable()從單。

相關問題