[英]setColorFilter is deprecated on API29
I use the following line to change the color of a VectorDrawable:我使用以下行来更改 VectorDrawable 的颜色:
mydrawable.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
This works nice, though it is now deprecated.这很好用,尽管它现在已被弃用。 The documentation suggests that I use:
文档建议我使用:
mydrawable.getBackground().setColorFilter(new BlendModeColorFilter(color, PorterDuff.Mode.SRC_ATOP))
Though, BlendModeColorFilter
is only available on API29.但是,
BlendModeColorFilter
仅在 API29 上可用。 After examining the source of the deprecated method, I have realized that it calls:在检查了弃用方法的来源后,我意识到它调用:
new PorterDuffColorFilter()
So, I went ahead and used:所以,我继续使用:
mydrawable.getBackground().setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP))
The coloring worked.着色工作。 Is this the right replacement for the deprecated method or I must use BlendModeColorFilter on API29?
这是已弃用方法的正确替代品,还是我必须在 API29 上使用 BlendModeColorFilter?
Thank you.谢谢你。
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);
UPDATE: Just use the latest version of the core androidx library and this code:更新:只需使用最新版本的核心 androidx 库和此代码:
mydrawable.colorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, BlendModeCompat.SRC_ATOP)
Use androidx.core:core:1.2.0
or androidx.core:core-ktx:1.2.0
.使用
androidx.core:core:1.2.0
或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))
Thanks to @shmakova I added a solution for Kotlin.感谢 @shmakova,我为 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:我尝试使用
BlendMode
和PorterDuff.Mode
参数(如drawable.setColorFilter(color, BlendMode.SRC_ATOP, PorterDuff.Mode.SRC_ATOP)
)调用setColorFilter
,但这导致运行时异常:
java.lang.NoClassDefFoundError: Failed resolution of: Landroid/graphics/BlendMode;
java.lang.NoClassDefFoundError:解析失败:Landroid/graphics/BlendMode;
So, we can call any method with BlendMode only starting from SDK version 29 (it was added there).因此,我们只能从 SDK 版本 29(它被添加到那里)开始使用BlendMode调用任何方法。 I had to create
setColorFilter
with Mode
parameter.我必须使用
Mode
参数创建setColorFilter
。
PorterDuffColorFilter
was added in API level 1 and it's not deprecated, in addition PorterDuffColorFilter
is a subclass of ColorFilter
. PorterDuffColorFilter
是在 API 级别 1 中添加的,并没有被弃用,此外PorterDuffColorFilter
是ColorFilter
的子类。 You may use it as you did with no problems as setColorFilter
parameter is of type ColorFilter
and it does not require you to pass a BlendModeColorFilter
.您可以像以前一样使用它,因为
setColorFilter
参数属于ColorFilter
类型,并且不需要您传递BlendModeColorFilter
。 The are many reasons why the documentation may suggests BlendModeColorFilter
.文档可能建议
BlendModeColorFilter
原因有很多。 Maybe they plan on deprecating PorterDuffColorFilter
in the future (as of 2021 it is still not deprecated) or maybe it just performs better, who knows... The point is that you used it correctly.也许他们计划在未来弃用
PorterDuffColorFilter
(截至 2021 年,它还没有被弃用),或者它的性能更好,谁知道呢……关键是你正确地使用了它。 If you want to safeguard against your code breaking down because PorterDuffColorFilter
suddenly got deprecated and removed then you should do what many others have suggested and add a Version check.如果您想防止您的代码因为
PorterDuffColorFilter
突然被弃用和删除而PorterDuffColorFilter
,那么您应该按照许多其他人的建议进行操作并添加版本检查。 If you are not worried about that then you don't have to do it but you will have to keep an eye out for any future changes.如果您不担心,那么您不必这样做,但您必须留意未来的任何变化。
But all in all as of 2021 your code will work on all versions.但总而言之,到 2021 年,您的代码将适用于所有版本。
Regards问候
NOTE: setColorFilter(int color, PorterDuff.Mode mode)
is deprecated this answer is only relevant to setColorFilter(ColorFilter colorFilter)
注意:
setColorFilter(int color, PorterDuff.Mode mode)
已弃用此答案仅与setColorFilter(ColorFilter colorFilter)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.