Android: cloner un dessin pour créer un StateListDrawable avec des filtres

J’essaie de créer une fonction de cadre général qui permette de mettre en évidence tout dessin dessiné lorsque vous appuyez / concentrez / sélectionnez / etc.

Ma fonction prend un Drawable et retourne un StateListDrawable, où l’état par défaut est Drawable, et l’état pour android.R.attr.state_pressed est identique, avec un filtre appliqué à l’aide de setColorFilter .

Mon problème est que je ne peux pas cloner le dessinable et en faire une instance séparée avec le filtre appliqué. Voici ce que j’essaie de réaliser:

 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; } 

Si je ne clone pas, le filtre est évidemment appliqué aux deux états. J’ai essayé de jouer avec mutate() mais ça n’aide pas ..

Des idées?

Mettre à jour:

La réponse acceptée clone en effet un dessinable. Cela ne m’a pas aidé parce que ma fonction générale échoue sur un autre problème. Il semble que lorsque vous ajoutez un dessinable à une StateList, il perd tous ses filtres.

Essayez ce qui suit:

 Drawable clone = drawable.getConstantState().newDrawable(); 

Si vous appliquez un filtre / etc à un dessinable créé avec getConstantState().newDrawable() toutes les instances de ce dessinable seront également modifiées, puisque les tirables utilisent le constantState comme cache!

Donc, si vous coloriez un cercle avec un filtre de couleur et newDrawable, vous allez changer la couleur de tous les cercles.

Si vous souhaitez que cet élément de mise à jour puisse être mis à jour sans affecter les autres instances, vous devez alors modifier cet état constant existant.

 // To make a drawable use a separate constant state drawable.mutate() 

Pour une bonne explication voir:

http://www.curious-creature.org/2009/05/02/drawable-mutations/

http://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate ()

Ceci est ma solution, basée sur cette question SO .

L’idée est ImageView obtient un filtre de couleur lorsque l’utilisateur le touche et que le filtre de couleur est supprimé lorsque l’utilisateur cesse de le toucher. Seulement 1 dessin / bitmap est en mémoire, donc pas besoin de le gaspiller. Cela fonctionne comme il se doit.

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

C’est ce qui fonctionne pour moi.

 Drawable clone = drawable.getConstantState().newDrawable().mutate(); 

J’ai répondu à une question connexe ici

Fondamentalement, il semble que StateListDrawables perd ses filtres. J’ai créé un nouveau BitmapDrawale à partir d’une copie modifiée de la bitmap que je voulais initialement utiliser.