Cara memperbaiki bug Drawable.setTint di API 21 Android SDK

Hai, dalam posting ini pengembang android kami Vlad Titov akan berbicara tentang cara mengatasi masalah menggunakan alat pengubah warna untuk Drawable. Pergilah.

Android SDK API versi ke-21 memperkenalkan alat universal untuk mengubah warna semua Drawable - Drawable.setTint (int color) . Tetapi hanya dalam versi ini, itu tidak berfungsi untuk beberapa pewaris Drawable, yaitu GradientDrawable, InsetDrawable, RippleDrawable, dan semua pewaris DrawableContainer. 

Jika kita melihat sumber API 21, katakanlah, GradientDrawable (keturunan langsung dari Drawable), kita tidak akan menemukan metode setTint yang diganti dan variasinya. Ini berarti bahwa dalam implementasi ini, pengembang sama sekali tidak mendukung fungsi ini.

. 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, , , .

, . 

Jika tint Anda hanya terdiri dari satu warna, Anda dapat melakukan hal berikut ini kapan saja:

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

Setelah itu, silakan lanjutkan bisnis Anda.

Jika tidak, masuk akal untuk menggunakan solusi berikut:

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

Solusi ini terlihat agak banyak, tetapi sepenuhnya menyelesaikan masalah yang ditunjukkan.




All Articles