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.
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.