I'm trying to tint an image prior to Android API level 21. I've successfully tinted items using:
<android:tint="@color/red"/>
However, I can't seem to figure out how to do this through code on an ImageView:
Drawable iconDrawable = this.mContext.getResources().getDrawable(R.drawable.somedrawable);
DrawableCompat.setTint(iconDrawable, this.mContext.getResources().getColor(R.color.red));
imageView.setImageDrawable(iconDrawable);
I've tried setting the TintMode but this seems to make no different. Am I using the v4 compatibility class DrawableCompat incorrectly?
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));
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));
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);
}
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.
来源:https://stackoverflow.com/questions/26788251/android-tint-using-drawablecompat