Comment corriger le bogue Drawable.setTint dans le SDK Android API 21

Bonjour, dans cet article, notre développeur Android Vlad Titov expliquera comment résoudre le problème à l'aide de l'outil de changement de couleur pour Drawable. Aller.

Dans la 21ème version de l'API Android SDK, il existe un outil universel pour changer la couleur de tous les Drawable - Drawable.setTint (int color) . Mais juste dans cette version même, cela ne fonctionne pas pour certains héritiers de Drawable, à savoir GradientDrawable, InsetDrawable, RippleDrawable et tous les héritiers de DrawableContainer. 

Si nous regardons les sources de l'API 21, disons GradientDrawable (descendant direct de Drawable), nous ne trouverons pas la méthode setTint remplacée et ses variations. Cela signifie que dans cette implémentation, les développeurs n'ont tout simplement pas pris en charge cette fonction.

. androidx.core:core. tinting 14-22, WrappedDrawableApi14 WrappedDrawableApi21. , , . 

Drawable, DrawableCompat.wrap(Drawable). , ColorStateList , Drawable Drawable.

final ColorStateList tintList = mState.mTint;
final PorterDuff.Mode tintMode = mState.mTintMode;

if (tintList != null && tintMode != null) {
   final int color = tintList.getColorForState(state, tintList.getDefaultColor());
   if (!mColorFilterSet || color != mCurrentColor || tintMode != mCurrentMode) {
       setColorFilter(color, tintMode);
       mCurrentColor = color;
       mCurrentMode = tintMode;
       mColorFilterSet = true;
       return true;
   }
} else {
   mColorFilterSet = false;
   clearColorFilter();
}

Drawable.setState(int[] stateSet).

Drawable. , , GradientDrawable , , setShape, setGradientType ... , Drawable (DrawableCompat.unwrap(Drawable)). . , , Drawable. stateful, , , .

, . 

Si votre teinte se compose d'une seule couleur, vous pouvez à tout moment effectuer les opérations suivantes:

val wrapped = DrawableCompat.wrap(drawable)
wrapped.setTint(...)
drawable = DrawableCompat.unwrap(wrapped)

Après cela, poursuivez votre activité avec audace.

Sinon, il est judicieux d'utiliser la solution suivante:

class GradientDrawableWrapper(
    val original: GradientDrawable, 
    var tint: ColorStateList
) {

    fun get(): Drawable {
        return wrap()
    }

    fun setShape(@Shape shape: Int) {
        original.setShape(shape)
    }

    // other specific method proxies...

    private fun wrap(): Drawable {
        val wrapped = DrawableCompat.wrap(original)
        wrapped.setTint(tint)
        return wrapped
    }
}

Cette solution semble un peu volumineuse, mais elle résout complètement le problème indiqué.




All Articles