0

I would like to change an existing drawable state list (default and pressed) colours programmatically.

This is my custom drawable I would like to edit:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <ripple android:color="#1AFFFFFF">
            <item>
                <shape android:shape="rectangle">
                    <solid android:color="@color/colorPrimary" />
                    <corners android:radius="5dp" />
                </shape>
            </item>
        </ripple>
    </item>
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimary" />
            <corners android:radius="5dp" />
        </shape>
    </item>
</selector>

I've tried How can I change colors in my StateListDrawable? but I am getting an error:

val customButtonTest: Drawable
    get() {
        val stateListDrawable = ContextCompat.getDrawable(context, R.drawable.custom_button) as StateListDrawable
        val drawableContainerState = stateListDrawable.constantState as DrawableContainer.DrawableContainerState
        val children = drawableContainerState.children
        val selectedItem = children[0] as GradientDrawable
        selectedItem.setColor(Color.parseColor("#FD00DF"))
        return stateListDrawable.current
    }


**ClassCastException: android.graphics.drawable.RippleDrawable cannot be cast to android.graphics.drawable.GradientDrawable**

As I am intend to use it for a BandingAdapter, how can I change both state colours and return it as a drawable?

Thanks

** Edited ---

val customButtonTest: Drawable
        get() {
            val stateListDrawable =
                ContextCompat.getDrawable(context, R.drawable.custom_button) as StateListDrawable
            val drawableContainerState =
                stateListDrawable.constantState as DrawableContainer.DrawableContainerState
            val children = drawableContainerState.children
            val pressedState = children[0] as RippleDrawable
            val defaultState = children[1] as GradientDrawable
            pressedState.setColor(ColorStateList.valueOf(Color.parseColor("#1AFFFFFF")))
            defaultState.setColor(Color.parseColor("#4267b2"))
            drawableContainerState.addChild(pressedState)
            drawableContainerState.addChild(defaultState)
            return drawableContainerState.newDrawable()
        }

How to change an item solid colour inside the ripple container? As

pressedState.setColor(ColorStateList.valueOf(Color.parseColor("#1AFFFFFF")

changes ripple colour itself.

Jonas Simonaitis
  • 170
  • 1
  • 13

1 Answers1

0

If someone needs to access ripple and its child, here you go:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <ripple android:color="#1A1C1C1C">
            <item>
                <shape android:shape="rectangle">
                    <solid android:color="@color/colorPrimary" />
                    <corners android:radius="5dp" />
                </shape>
            </item>
        </ripple>
    </item>
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimary" />
            <corners android:radius="5dp" />
        </shape>
    </item>
</selector>

  val customButtonTest: Drawable
    get() {
        val stateListDrawable = ContextCompat.getDrawable(context, R.drawable.custom_button) as StateListDrawable
        val drawableContainerState = stateListDrawable.constantState as DrawableContainer.DrawableContainerState
        val children = drawableContainerState.children
        val pressedState = children[0] as RippleDrawable
        val defaultState = children[1] as GradientDrawable
        val layerDrawable = pressedState as LayerDrawable
        val rippleChildDrawable = layerDrawable.getDrawable(0) as GradientDrawable

        rippleChildDrawable.setColor(primaryColor)
        defaultState.setColor(primaryColor)

        return drawableContainerState.newDrawable()
    }

To reach <items> inside <ripple> you need to cast RippleDrawable to LayerDrawable

Jonas Simonaitis
  • 170
  • 1
  • 13