Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Cloning a drawable in order to make a StateListDrawable with filters

I'm trying to make a general framework function that makes any Drawable become highlighted when pressed/focused/selected/etc.

My function takes a Drawable and returns a StateListDrawable, where the default state is the Drawable itself, and the state for android.R.attr.state_pressed is the same drawable, just with a filter applied using setColorFilter.

My problem is that I can't clone the drawable and make a separate instance of it with the filter applied. Here is what I'm trying to achieve:

StateListDrawable makeHighlightable(Drawable drawable) {     StateListDrawable res = new StateListDrawable();      Drawable clone = drawable.clone(); // how do I do this??      clone.setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);     res.addState(new int[] {android.R.attr.state_pressed}, clone);     res.addState(new int[] { }, drawable);     return res; } 

If I don't clone then the filter is obviously applied to both states. I tried playing with mutate() but it doesn't help..

Any ideas?

Update:

The accepted answer indeed clones a drawable. It didn't help me though because my general function fails on a different problem. It seems that when you add a drawable to a StateList, it loses all its filters.

like image 993
talkol Avatar asked Nov 02 '11 11:11

talkol


People also ask

What is layerdrawable?

A Drawable that manages an array of other Drawables. These are drawn in array order, so the element with the largest index will be drawn on top. It can be defined in an XML file with the <layer-list> element. Each Drawable in the layer is defined in a nested <item> .

What is StateListDrawable?

State value for StateListDrawable , set when a view's window has input focus. android:variablePadding. If true, allows the drawable's padding to change based on the current state that is selected.


2 Answers

Try the following:

Drawable clone = drawable.getConstantState().newDrawable(); 
like image 172
Flavio Avatar answered Sep 21 '22 20:09

Flavio


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()

like image 44
Peter Ajtai Avatar answered Sep 22 '22 20:09

Peter Ajtai