setColorFilter is deprecated on API29

前端 未结 3 1838
眼角桃花
眼角桃花 2020-12-09 14:40

I use the following line to change the color of a VectorDrawable:

mydrawable.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP)

Thi

相关标签:
3条回答
  • 2020-12-09 14:55

    Try this:

    public class MyDrawableCompat {
        public static void setColorFilter(@NonNull Drawable drawable, @ColorInt int color) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                drawable.setColorFilter(new BlendModeColorFilter(color, BlendMode.SRC_ATOP));
            } else {
                drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
            }
        }
    }
    

    And this:

    MyDrawableCompat.setColorFilter(mydrawable.getBackground(), color);
    
    0 讨论(0)
  • 2020-12-09 15:02

    Thanks to @shmakova I added a solution for Kotlin.

    import android.graphics.BlendMode
    import android.graphics.BlendModeColorFilter
    import android.graphics.PorterDuff
    import android.graphics.drawable.Drawable
    import android.os.Build
    import androidx.annotation.RequiresApi
    
    fun Drawable.setColorFilter(color: Int, mode: Mode = Mode.SRC_ATOP) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            colorFilter = BlendModeColorFilter(color, mode.getBlendMode())
        } else {
            @Suppress("DEPRECATION")
            setColorFilter(color, mode.getPorterDuffMode())
        }
    }
    
    // This class is needed to call the setColorFilter 
    // with different BlendMode on older API (before 29).
    enum class Mode {
        CLEAR,
        SRC,
        DST,
        SRC_OVER,
        DST_OVER,
        SRC_IN,
        DST_IN,
        SRC_OUT,
        DST_OUT,
        SRC_ATOP,
        DST_ATOP,
        XOR,
        DARKEN,
        LIGHTEN,
        MULTIPLY,
        SCREEN,
        ADD,
        OVERLAY;
    
        @RequiresApi(Build.VERSION_CODES.Q)
        fun getBlendMode(): BlendMode =
            when (this) {
                CLEAR -> BlendMode.CLEAR
                SRC -> BlendMode.SRC
                DST -> BlendMode.DST
                SRC_OVER -> BlendMode.SRC_OVER
                DST_OVER -> BlendMode.DST_OVER
                SRC_IN -> BlendMode.SRC_IN
                DST_IN -> BlendMode.DST_IN
                SRC_OUT -> BlendMode.SRC_OUT
                DST_OUT -> BlendMode.DST_OUT
                SRC_ATOP -> BlendMode.SRC_ATOP
                DST_ATOP -> BlendMode.DST_ATOP
                XOR -> BlendMode.XOR
                DARKEN -> BlendMode.DARKEN
                LIGHTEN -> BlendMode.LIGHTEN
                MULTIPLY -> BlendMode.MULTIPLY
                SCREEN -> BlendMode.SCREEN
                ADD -> BlendMode.PLUS
                OVERLAY -> BlendMode.OVERLAY
            }
    
        fun getPorterDuffMode(): PorterDuff.Mode =
            when (this) {
                CLEAR -> PorterDuff.Mode.CLEAR
                SRC -> PorterDuff.Mode.SRC
                DST -> PorterDuff.Mode.DST
                SRC_OVER -> PorterDuff.Mode.SRC_OVER
                DST_OVER -> PorterDuff.Mode.DST_OVER
                SRC_IN -> PorterDuff.Mode.SRC_IN
                DST_IN -> PorterDuff.Mode.DST_IN
                SRC_OUT -> PorterDuff.Mode.SRC_OUT
                DST_OUT -> PorterDuff.Mode.DST_OUT
                SRC_ATOP -> PorterDuff.Mode.SRC_ATOP
                DST_ATOP -> PorterDuff.Mode.DST_ATOP
                XOR -> PorterDuff.Mode.XOR
                DARKEN -> PorterDuff.Mode.DARKEN
                LIGHTEN -> PorterDuff.Mode.LIGHTEN
                MULTIPLY -> PorterDuff.Mode.MULTIPLY
                SCREEN -> PorterDuff.Mode.SCREEN
                ADD -> PorterDuff.Mode.ADD
                OVERLAY -> PorterDuff.Mode.OVERLAY
            }
    }
    

    Use it as usually:

    toolbar?.navigationIcon?.setColorFilter(ContextCompat.getColor(this, color)) /* 1 */
    progressBar.indeterminateDrawable.setColorFilter(color, Mode.SRC_IN) /* 2 */
    

    I tried to call setColorFilter with both BlendMode and PorterDuff.Mode parameters (like drawable.setColorFilter(color, BlendMode.SRC_ATOP, PorterDuff.Mode.SRC_ATOP)), but that led to a runtime exception:

    java.lang.NoClassDefFoundError: Failed resolution of: Landroid/graphics/BlendMode;

    So, we can call any method with BlendMode only starting from SDK version 29 (it was added there). I had to create setColorFilter with Mode parameter.

    0 讨论(0)
  • 2020-12-09 15:03

    Use androidx.core:core:1.2.0 or androidx.core:core-ktx:1.2.0.

    // Java
    implementation 'androidx.core:core:1.2.0'
    // Kotlin
    implementation 'androidx.core:core-ktx:1.2.0'
    

    And this:

    drawable.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, BlendModeCompat.SRC_ATOP))
    
    0 讨论(0)
提交回复
热议问题