I\'m trying to make a general framework function that makes any Drawable become highlighted when pressed/focused/selected/etc.
My function takes a D
Get clone drawable using newDrawable()
but make sure it is mutable otherwise your clone effect gone, I used these few lines of code and it is working as expected. getConstantState()
may be null as suggested by annotation, so handle this RunTimeException while you cloning drawable.
Drawable.ConstantState state = d.mutate().getConstantState();
if (state != null) {
Drawable drawable = state.newDrawable().mutate();
}
If you apply a filter / etc to a drawable created with getConstantState().newDrawable()
then all instances of that drawable will be changed as well, since drawables use the constantState
as a cache!
So if you color a circle using a color filter and a newDrawable()
, you will change the color of all the circles.
If you want to make this drawable updatable without affecting other instances then, then you must mutate that existing constant state.
// To make a drawable use a separate constant state
drawable.mutate()
For a good explanation see:
http://www.curious-creature.org/2009/05/02/drawable-mutations/
http://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate()
This is what works for me.
Drawable clone = drawable.getConstantState().newDrawable().mutate();
Try the following:
Drawable clone = drawable.getConstantState().newDrawable();
I answered a related question here
Basically it seems like StateListDrawables indeed lose their filters. I created a new BitmapDrawale from a altered copy of the Bitmap I originally wanted to use.
This is my solution, based on this SO question.
The idea is that ImageView
gets color filter when user touches it, and color filter is removed when user stops touching it. Only 1 drawable/bitmap is in memory, so no need to waste it. It works as it should.
class PressedEffectStateListDrawable extends StateListDrawable {
private int selectionColor;
public PressedEffectStateListDrawable(Drawable drawable, int selectionColor) {
super();
this.selectionColor = selectionColor;
addState(new int[] { android.R.attr.state_pressed }, drawable);
addState(new int[] {}, drawable);
}
@Override
protected boolean onStateChange(int[] states) {
boolean isStatePressedInArray = false;
for (int state : states) {
if (state == android.R.attr.state_pressed) {
isStatePressedInArray = true;
}
}
if (isStatePressedInArray) {
super.setColorFilter(selectionColor, PorterDuff.Mode.MULTIPLY);
} else {
super.clearColorFilter();
}
return super.onStateChange(states);
}
@Override
public boolean isStateful() {
return true;
}
}
usage:
Drawable drawable = new FastBitmapDrawable(bm);
imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));