Android: Tint using DrawableCompat

丶灬走出姿态 提交于 2019-11-27 06:24:55

The simplest way to tint cross-platform (if you don't need a ColorStateList) is:

drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);

Don't forget to mutate the Drawable before applying the filter.

In case anyone needs to use DrawableCompat's tinting without affecting other drawables, here's how you do it with 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));

Which can be simplified to:

Drawable drawable = getResources().getDrawable(R.drawable.some_drawable);
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(drawable.mutate(), getResources().getColor(R.color.white));
Simon K. Gerges

Previously tinting was not supported by DrawableCompat. Starting from support library 22.1 you can do that, but you need do it in this way:

Drawable normalDrawable = getResources().getDrawable(R.drawable.drawable_to_tint);
Drawable wrapDrawable = DrawableCompat.wrap(normalDrawable);
DrawableCompat.setTint(wrapDrawable, getResources().getColor(R.color.colorPrimaryLight));
hardysim

The answers here are not working for pre-lollipop-devices (SupportLib 23.4.0) but I've posted a workaround which is working for API 17 and up: https://stackoverflow.com/a/37434219/2170109

The following code was tested and is working on APIs 17, 19, 21, 22, 23 and N Preview 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);
    }
Michael Smith

If you look at the source code for DrawableCompat you will see that for any version < 21 the method does nothing.

The idea of DrawableCompat seems to be simply not crashing on old versions, rather than actually providing that functionality.

With support library 22.1 you can use DrawableCompat to tint drawables.

DrawableCompat.wrap(Drawable) and setTint(), setTintList(), and setTintMode() will just work: no need to create and maintain separate drawables only to support multiple colors!

I'll share my solution here because it may save some time to somebody.

I had an ImageView with vector drawable used as its source drawable (actually, it was Support Vector Drawable from Android Support Library 23.3). So, first I've wrapped it like so:

mImageView.setImageDrawable(DrawableCompat.wrap(mImageView.getDrawable()));

And after that I tried to apply tint to it like so:

DrawableCompat.setTint(
    mImageView.getDrawable(),
    getResources().getColor(R.color.main_color)
);

No luck.

I tried to call mutate() on wrapped drawable, as well as on original drawable - still no luck. invalidate() called on mImageView did the trick.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!