Ответ 1
Попробуйте следующее:
Drawable clone = drawable.getConstantState().newDrawable();
Я пытаюсь создать общую функцию фреймворка, которая позволяет выделить любой Drawable, когда нажата/сфокусирована/выбрана/etc.
Моя функция принимает 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()
, но это не помогает..
Любые идеи?
Update:
Принятый ответ действительно клонирует приемлемый. Это мне не помогло, потому что моя общая функция не срабатывает по другой проблеме. Кажется, что когда вы добавляете drawable в StateList, он теряет все свои фильтры.
Попробуйте следующее:
Drawable clone = drawable.getConstantState().newDrawable();
Если вы примените фильтр /etc к чертежу, созданному с помощью getConstantState().newDrawable()
, тогда будут также изменены все экземпляры этого drawable, так как drawables используют constantState
как кеш!
Итак, если вы покрасьте круг с цветовым фильтром и newDrawable, вы измените цвет всех кругов.
Если вы хотите, чтобы сделать этот drawable updatable без влияния на другие экземпляры, тогда вы должны мутировать существующее существующее состояние.
// 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()
Это мое решение, основанное на этом коде: fooobar.com/questions/78311/.... Идея заключается в том, что 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));
Это то, что работает для меня.
Drawable clone = drawable.getConstantState().newDrawable().mutate();
Я ответил на соответствующий вопрос здесь
В принципе, похоже, что StateListDrawables действительно теряют свои фильтры. Я создал новый BitmapDrawale из измененной копии растрового изображения, которое я первоначально хотел использовать.