Android: клонирование отрисовки для создания StateListDrawable с фильтрами - PullRequest
86 голосов
/ 02 ноября 2011

Я пытаюсь сделать общую каркасную функцию, которая делает любой Drawable выделенным, когда нажат / сфокусирован / выбран / и т.д. .

Моя функция берет Drawable и возвращает StateListDrawable,где состоянием по умолчанию является сам Drawable, а состояние для android.R.attr.state_pressed такое же, что и для рисования, только с фильтром, примененным с использованием setColorFilter.

Моя проблема в том, что я не могу клонировать ничью и сделатьотдельный экземпляр с примененным фильтром.Вот что я пытаюсь достичь:

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

Если я не клонирую, тогда фильтр, очевидно, применяется к обоим состояниям.Я пытался играть с mutate(), но это не помогает ..

Есть идеи?

Обновление:

Принятый ответ действительно клонируетвытяжка.Это не помогло мне, хотя, потому что моя общая функция не работает из-за другой проблемы.Кажется, что когда вы добавляете drawable в StateList, он теряет все свои фильтры.

Ответы [ 5 ]

153 голосов
/ 02 ноября 2011

Попробуйте следующее:

Drawable clone = drawable.getConstantState().newDrawable();
98 голосов
/ 31 августа 2013

Если вы примените фильтр / etc к рисованному объекту, созданному с помощью getConstantState().newDrawable(), то все экземпляры этого рисованного объекта также будут изменены, так как в чертежном объекте constantState используется в качестве кэша!

Так что, если вы раскрасите круг, используя цветной фильтр и newDrawable(), вы измените цвет всех кругов.

Если вы хотите, чтобы этот объект рисования можно было обновлять, не затрагивая другие экземпляры, тогда вы должны изменить это существующее постоянное состояние.

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

Хорошее объяснение см:

http://www.curious -creature.org / 2009/05/02 / вытяжке мутации /

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

13 голосов
/ 25 марта 2017

Это то, что у меня работает.

Drawable clone = drawable.getConstantState().newDrawable().mutate();
10 голосов
/ 28 января 2014

Это мое решение, основанное на этом ТАКОМ вопросе .

Идея состоит в том, что ImageView получает цветной фильтр, когда пользователь прикасается к нему, и цветной фильтр удаляется, когда пользователь перестает прикасаться к нему.В памяти только 1 рисованный / растровый рисунок, поэтому не нужно тратить его впустую.Работает как надо.

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

использование:

Drawable drawable = new FastBitmapDrawable(bm);
imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));
1 голос
/ 13 мая 2012

Я ответил на связанный вопрос здесь

В основном кажется, что StateListDrawables действительно теряют свои фильтры. Я создал новый BitmapDrawale из измененной копии растрового изображения, которое изначально хотел использовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...