I have the following code for my ripple:
<?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>
Now I want to give the user the possibility to choose own colors, so I need to create the ripple programmatically.
I found this and I think this is the right way to do it, but I don't know how to handle with this.
The ripple will be used here:
<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" />
I need to set the background to a RippleDrawable
like this:
addButton.setBackground(ripple);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With