androidandroid-5.0-lollipoprippledrawable

How to use RippleDrawable programmatically in code (not xml) with Android 5.0 Lollipop?


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

Solution

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