How to apply color filters to specific drawables in a StateListDrawable?

android, colorfilter, statelistdrawable

Solution

To work around this, you have to apply the color filter to the `StateListDrawable` itself, based on the state the drawable is in. The following extension of `StateListDrawable` accomplishes this.

public class SelectorDrawable extends StateListDrawable {

    public SelectorDrawable(Context c) {
        super();

        addState(new int[] {android.R.attr.state_pressed}, c.getResources().getDrawable(R.drawable.solid_green));
        // Other states...
    }

    @Override
    protected boolean onStateChange(int[] states) {
        boolean isClicked = false;
        for (int state : states) {
            if (state == android.R.attr.state_pressed) {
                isClicked = true;
            }
        }

        if (isClicked)
            setColorFilter(Color.RED, PorterDuff.Mode.SRC);
        else
            clearColorFilter();

        return super.onStateChange(states);
    }
}

The logic in `onStateChange(int[] states)` can be extended further to test for more than just the pressed state, and different color filters can be applied accordingly.

Problem

It seems that `StateListDrawable` will ignore color filters applied to the drawables they contain. For example: ``` StateListDrawable sld = new StateListDrawable(); Drawable pressedState = Context.getResources().getDrawable(R.drawable.solid_green); pressedState.setColorFilter(Color.RED, PorterDuff.Mode.SRC); sld.addState(new int[] {android.R.attr.state_pressed}, pressedState); // Other states... ``` If you apply `sld` to a view's background, you would expect the view's background to turn solid red when it is pressed. Instead, it would turn green - the color of `pressedState` with no filters applied.

Original source