Hannes Struß
Hannes Struß

Reputation: 1569

Wrapping a StateListDrawable

I have a view, on which I set a StateListDrawable (defines state_pressed and the default state) as a the background in XML. This works fine, all the states are displayed as expected.

I now want to programmatically draw something on top of the StateListDrawable, no matter in which state it is. For this, I created a Java class that extends Drawable, which holds the original background drawable; in onDraw it first draws the original drawable to the canvas and then its own additions. This also works, but the state of the original drawable doesn't change.

I can see that setState of my custom Drawable is called with a stateSet that contains android.R.attr.state_pressed among some other states. I delegate that call to the original drawable, but there setState always returns false and its state doesn't change. It only changes when I pass a stateSet containing nothing but android.R.attr.state_pressed.

It seems as if the StateListDrawable somehow can announce the stateSets it is interested in and the caller of setState respecting that, although I didn't find anything related in the docs or the Android source.

This is my setState:

@Override public boolean setState(int[] stateSet) {
    boolean changed = super.setState(stateSet);
    if (originalBackground != null) {
        // this call only returns true and changes the state if
        // the stateSet *only* contains the pressed state
        changed |= originalBackground.setState(stateSet);
    }
    return true;
}

My original background Drawable:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
          android:drawable="@color/red"/>
    <item android:drawable="@color/green"/>
</selector>

How can I make the original drawable change its state without filtering the stateSet for state_pressed?

Upvotes: 0

Views: 442

Answers (1)

Hannes Stru&#223;
Hannes Stru&#223;

Reputation: 1569

Thanks to pskink's example I tried calling invalidateSelf in onStateChanged, which did the trick.

Upvotes: 1

Related Questions