Я пытаюсь создать общую функцию фреймворка, которая заставляет любой Drawable выделяться при нажатии / фокусировке / выборе / и т . Д.
Моя функция принимает Drawable и возвращает StateListDrawable, где состояние по умолчанию - это сам Drawable, а состояние for android.R.attr.state_pressed
такое же drawable, только с примененным фильтром с использованием 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()
но это не помогает ..
Любые идеи?
Обновить:
Принятый ответ действительно клонирует возможность рисования. Но это не помогло мне, потому что моя общая функция не работает по другой проблеме. Похоже, что когда вы добавляете объект в StateList, он теряет все свои фильтры.
источник
ImageView.setImageDrawable
, который я смог обойти благодаря принятому ответу.Ответы:
Попробуйте следующее:
Drawable clone = drawable.getConstantState().newDrawable();
источник
.mutate()
(см. Мой ответ).Если вы примените фильтр / etc к рисованному объекту, созданному с помощью,
getConstantState().newDrawable()
тогда все экземпляры этого рисованного объекта также будут изменены, поскольку рисованные объекты используют вconstantState
качестве кеша!Итак, если вы раскрасите круг с помощью цветового фильтра и символа a
newDrawable()
, вы измените цвет всех кругов.Если вы хотите сделать этот доступный для рисования обновляемым, не затрагивая другие экземпляры, тогда вы должны изменить это существующее постоянное состояние.
// To make a drawable use a separate constant state drawable.mutate()
Для хорошего объяснения см .:
http://www.curious-creature.org/2009/05/02/drawable-mutations/
http://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate ()
источник
Это то, что у меня работает.
Drawable clone = drawable.getConstantState().newDrawable().mutate();
источник
Это мое решение, основанное на этом вопросе SO .
Идея состоит в том, что
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));
источник
Я ответил на связанный с этим вопрос здесь
По сути, кажется, что StateListDrawables действительно теряет свои фильтры. Я создал новый BitmapDrawale из измененной копии Bitmap, которую я изначально хотел использовать.
источник
в случае
getConstantState()
возвратаnull
.источник
Получите возможность клонирования с помощью,
newDrawable()
но убедитесь, что он изменяемый, иначе ваш эффект клонирования исчезнет, я использовал эти несколько строк кода, и он работает, как ожидалось.getConstantState()
может иметь значение null, как предлагается аннотацией, поэтому обработайте это RunTimeException при клонировании drawable.Drawable.ConstantState state = d.mutate().getConstantState(); if (state != null) { Drawable drawable = state.newDrawable().mutate(); }
источник