Próbuję stworzyć ogólną funkcję ramową, która sprawia, że każdy Drawable zostanie podświetlony po naciśnięciu / skupieniu / wybraniu / itp .
Moja funkcja przyjmuje Drawable i zwraca StateListDrawable, gdzie domyślnym stanem jest sam Drawable, a stan dla android.R.attr.state_pressed
jest taki sam do rysowania, tylko z filtrem zastosowanym przy użyciu setColorFilter
.
Mój problem polega na tym, że nie mogę sklonować tego, co można narysować, i utworzyć oddzielną instancję z zastosowanym filtrem. Oto, co próbuję osiągnąć:
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;
}
Jeśli nie klonuję, filtr jest oczywiście stosowany do obu stanów. Próbowałem się bawić, mutate()
ale to nie pomaga ...
Jakieś pomysły?
Aktualizacja:
Zaakceptowana odpowiedź rzeczywiście klonuje element do wyciągnięcia. Nie pomogło mi to jednak, ponieważ moja ogólna funkcja zawodzi w innym problemie. Wygląda na to, że kiedy dodajesz drawable do StateList, traci wszystkie swoje filtry.
źródło
ImageView.setImageDrawable
, który udało mi się obejść dzięki zaakceptowanej odpowiedzi.Odpowiedzi:
Spróbuj wykonać następujące czynności:
Drawable clone = drawable.getConstantState().newDrawable();
źródło
.mutate()
(zobacz moją odpowiedź).Jeśli zastosujesz filtr / etc do elementu do rysowania utworzonego za pomocą,
getConstantState().newDrawable()
wszystkie wystąpienia tego elementu do rysowania również zostaną zmienione, ponieważ elementy do rysowania używająconstantState
jako pamięci podręcznej!Więc jeśli pokolorujesz okrąg za pomocą filtra kolorów i a
newDrawable()
, zmienisz kolor wszystkich okręgów.Jeśli chcesz, aby ten możliwy do rysowania był aktualizowany bez wpływu na inne instancje, musisz zmodyfikować ten istniejący stały stan.
// To make a drawable use a separate constant state drawable.mutate()
Aby uzyskać dobre wyjaśnienie, zobacz:
http://www.curious-creature.org/2009/05/02/drawable-mutations/
http://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate ()
źródło
To właśnie działa dla mnie.
Drawable clone = drawable.getConstantState().newDrawable().mutate();
źródło
To jest moje rozwiązanie oparte na tym pytaniu SO .
Chodzi o to, że
ImageView
filtr koloru jest pobierany, gdy użytkownik go dotknie, a filtr koloru jest usuwany, gdy użytkownik przestaje go dotykać. W pamięci jest tylko 1 rysowalna / bitmapa, więc nie ma potrzeby jej marnować. Działa tak, jak powinno.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; } }
stosowanie:
Drawable drawable = new FastBitmapDrawable(bm); imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));
źródło
I odpowiedział powiązane pytanie tutaj
Zasadniczo wygląda na to, że StateListDrawables rzeczywiście tracą swoje filtry. Utworzyłem nowy BitmapDrawale ze zmienionej kopii Bitmapy, której pierwotnie chciałem użyć.
źródło
w przypadku
getConstantState()
zwrotównull
.źródło
Uzyskaj możliwość rysowania klonów za pomocą,
newDrawable()
ale upewnij się, że jest zmienny, w przeciwnym razie efekt klonowania zniknie. Użyłem tych kilku wierszy kodu i działa zgodnie z oczekiwaniami.getConstantState()
może być null, jak sugeruje adnotacja, więc obsłuż ten wyjątek RunTimeException podczas klonowania do rysowania.Drawable.ConstantState state = d.mutate().getConstantState(); if (state != null) { Drawable drawable = state.newDrawable().mutate(); }
źródło