2015-01-05 5 views
26

У меня есть следующий код для моей пульсации:Как использовать RippleDrawable программно в коде (не xml) с Android 5.0 Lollipop?

<?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); 
} 

Edit: я возился с этим еще немного и обнаружил, что ColorStateList не нужно быть столь же сложным, как выше решение. Я упростил его до следующего фрагмента. (Все остальное в приведенном выше блоке кода одинаково. Я только изменил создание ColorStateList.) Я оставлю этот блок в качестве оригинала, если этот метод не работает для кого-то.

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

Спасибо, ОЧЕНЬ много для вас ответ :) (Не могу дать вам преимущество, недостаточно репутации). – 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.
Для устройств Lollipop + вы получите пульсацию, иначе он изменит цвет обзора.

+0

Это приятно. Недостатком, я думаю, является то, что он может потерять закругленные углы при применении на устройстве с предварительным лепестком, потому что 'ColorDrawable' в 'StateListDrawable' не имеют формы. Вместо этого мы можем предоставить цветную форму ShapeDrawable, чтобы сохранить форму. Но, возможно, это начнет становиться немного тяжелым.В этом случае еще одним решением было бы создать пользовательский «ColorStateDrawable» с методом «setColor», чтобы вы не могли повторно создать все объекты, необходимые для StateListDrawable. – John

+0

Найдите что-то здесь: https://github.com/gabrielemariotti/colorpickercollection/blob/master/ColorPicker/src/it/gmariotti/android/example/colorpicker/calendarstock/ColorStateDrawable.java – John

2

В принципе, вам нужно создать новый объект RippleDrawable. Для устройств pre-Lollipop вы хотите StateListDrawable (как уже указывали другие). Я написал несколько изобретательный GIST с кучей полезных методов, связанных с окраской и вводимого коэффициента: https://gist.github.com/milosmns/6566ca9e3b756d922aa5

Скорее всего, вы будете хотеть использовать #getBackgroundDrawable() из этого синглтон.