Android:Tint使用DrawableCompat

Hip*_*mus 48 compatibility android tint

我试图在Android API级别21之前对图像进行着色.我已成功使用以下项目着色项目:

<android:tint="@color/red"/>
Run Code Online (Sandbox Code Playgroud)

但是,我似乎无法弄清楚如何通过ImageView上的代码执行此操作:

Drawable iconDrawable = this.mContext.getResources().getDrawable(R.drawable.somedrawable);
DrawableCompat.setTint(iconDrawable, this.mContext.getResources().getColor(R.color.red));
imageView.setImageDrawable(iconDrawable);
Run Code Online (Sandbox Code Playgroud)

我已经尝试过设置TintMode,但这似乎没有什么不同.我是否错误地使用了v4兼容类DrawableCompat?

Ren*_*ari 121

如果有人需要使用DrawableCompat的着色而不影响其他绘图,这里是你如何做到这一点mutate():

Drawable drawable = getResources().getDrawable(R.drawable.some_drawable);
Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
wrappedDrawable = wrappedDrawable.mutate();
DrawableCompat.setTint(wrappedDrawable, getResources().getColor(R.color.white));
Run Code Online (Sandbox Code Playgroud)

哪个可以简化为:

Drawable drawable = getResources().getDrawable(R.drawable.some_drawable);
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(drawable.mutate(), getResources().getColor(R.color.white));
Run Code Online (Sandbox Code Playgroud)

  • mutate()是正确的方法.没有它,你就会为整个应用程序全局着色drawable.引用javadoc:"一个可变的drawable保证不与任何其他drawable共享它的状态.当你需要修改从资源加载的drawable的属性时,这尤其有用.默认情况下,从同一资源加载的所有drawables实例共享一个common state;如果你修改一个实例的状态,所有其他实例都将收到相同的修改." (22认同)
  • 适用于4.1及更高版本(API 16及更高版本).使用最新的支持库(23.1.1)进行测试.变异至少需要4.1.适用于21和23. (3认同)
  • 如果需要使用选择器,请使用`DrawableCompat.setTintList()`. (3认同)
  • 这适用于API 19和API 23,但不适用于API 21. (2认同)

Sim*_*ges 53

之前的着色不受支持DrawableCompat.从支持库22.1开始,您可以这样做,但您需要以这种方式执行此操作:

Drawable normalDrawable = getResources().getDrawable(R.drawable.drawable_to_tint);
Drawable wrapDrawable = DrawableCompat.wrap(normalDrawable);
DrawableCompat.setTint(wrapDrawable, getResources().getColor(R.color.colorPrimaryLight));
Run Code Online (Sandbox Code Playgroud)

  • 这适用于API级别23和API级别19,但不适用于API级别21. (2认同)

Bla*_*der 45

跨平台着色的最简单方法(如果您不需要ColorStateList)是:

drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
Run Code Online (Sandbox Code Playgroud)

在应用过滤器之前,不要忘记改变Drawable.

  • 不确定为什么有人对此进行了低估,但这段代码实际上是AppCompat在以前的Android版本中所做的.AppCompat API执行此操作非常冗长,因此与此代码相比,我认为使用它并不会带来太多好处. (2认同)

har*_*sim 30

这里的答案是不工作的预棒棒糖设备(SupportLib 23.4.0),但我已经发布了一个解决办法,其工作API 17以上:/sf/answers/2620395361/

以下代码已经过测试,正在开发API 17,19,21,22,23和N预览版3:

    // https://stackoverflow.com/a/30928051/2170109
    Drawable drawable = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.vector));
    image.setImageDrawable(drawable);

    /*
     * need to use the filter | https://stackoverflow.com/a/30880522/2170109
     * (even if compat should use it for pre-API21-devices | https://stackoverflow.com/a/27812472/2170109)
     */
    int color = ContextCompat.getColor(context, R.color.yourcolor);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        DrawableCompat.setTint(drawable, color);

    } else {
        drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
    }
Run Code Online (Sandbox Code Playgroud)


Mic*_*ith 6

如果你查看DrawableCompat的源代码,你会发现对于任何版本<21,该方法什么都不做.

DrawableCompat的想法似乎不是在旧版本上崩溃,而是实际提供该功能.

  • 如果您实际上遵循使用哪个类,您将看到`DrawableWrapper`使用滤色器实现色调. (11认同)