100 votes

Android: Clonage d'un drawable afin de faire un StateListDrawable avec des filtres

Je suis en train de faire un cadre général de la fonction qui fait tout Drawable mis en valeur lors de la pressée/choisi/etc.

Ma fonction prend un Drawable et renvoie un StateListDrawable, où l'état par défaut est le Drawable lui-même, et l'état d' android.R.attr.state_pressed est le même drawable, juste avec un filtre appliqué à l'aide d' setColorFilter.

Mon problème est que je ne peux pas cloner le drawable et de faire une instance séparée de celui-ci avec le filtre appliqué. Voici ce que je suis en train 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 n'ai pas de clone, puis le filtre est évidemment appliqué à deux états. J'ai essayé de jouer avec mutate() mais il n'aide pas..

Des idées?

Mise à jour:

La accepté de répondre, en effet, les clones d'un drawable. Il ne m'a pas aidé, mais parce que mes générale de la fonction échoue sur un problème différent. Il semble que lorsque vous ajoutez un drawable à un StateList, elle perd tous ses filtres.

176voto

Flavio Points 1716

Essayez les solutions suivantes:

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

116voto

Peter Ajtai Points 26377

Si vous appliquez un filtre / etc à un drawable créé avec getConstantState().newDrawable() alors toutes les instances de cette drawable sera changé, depuis un drawable utiliser l' constantState comme un cache!

Donc, si vous la couleur d'un cercle avec filtre de couleur et newDrawable, vous pourrez changer la couleur de tous les cercles.

Si vous souhaitez obtenir de faire de cette drawable pouvant être mis à jour sans affecter les autres instances, puis, alors vous devez muter existants état constant.

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

12voto

Malachiasz Points 1537

C'est ma solution, basée sur ce code: http://stackoverflow.com/a/6071813/2075875. L'idée est que ImageView obtient filtre de couleur lorsque l'utilisateur touche, et la couleur du filtre est supprimé lorsque l'utilisateur arrête de la toucher. Seulement 1 drawable/bitmap en mémoire, donc pas besoin de gaspiller. Il 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;
    }
}

utilisation:

Drawable drawable = new FastBitmapDrawable(bm);
imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));

1voto

Kuno Points 692

J'ai répondu à une question relative à la ici

Fondamentalement, il semble que StateListDrawables en effet de perdre leurs filtres. J'ai créé un nouveau BitmapDrawale à partir d'une altération de la copie de l'image Bitmap au départ je voulais utiliser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X