How to use RippleDrawable programmatically in code (not xml) with Android 5.0 Lollipop?
This is how I was able to achieve this.
Note that this is Api 21+ only so you will have to fallback to a normal Drawable if you support lower versions.
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:I tinkered with this some more and discovered that the ColorStateList doesn't need to be nearly as complex as the above solution. I have simplified it to the below snippet. (Everything else in the above code block is the same. I only changed the ColorStateList creation.) I will leave the above block as the original, in case this method doesn't work for someone.
new ColorStateList( new int[][] { new int[]{} }, new int[] { pressedColor });
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;}
You can get the drawable and apply to any view using view.setDrawable
.
For Lollipop+ devices you will get ripple else it will change the color of view.
Basically, you need to create a new RippleDrawable object. For pre-Lollipop devices, you want a StateListDrawable (as others already suggested). I've written a somewhat resourceful GIST with a bunch of useful methods related to Drawables and coloring:https://gist.github.com/milosmns/6566ca9e3b756d922aa5
Most likely you will want to use #getBackgroundDrawable()
from that singleton.