Reputation: 531
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?
Upvotes: 52
Views: 41442
Reputation: 3963
to set a tint and a drawable to a view and make it backward compatible while supporting the current theme of context using kotlin and not checking for the current SDK version and avoid deprecated methods:
imageView.setImageDrawable(
ContextCompat.getDrawable(context, R.drawable.somedrawable).apply {
setTint(ContextCompat.getColor(context, R.color.red))
})
Upvotes: 0
Reputation: 717
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.
Upvotes: 6
Reputation: 2866
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);
}
Upvotes: 30
Reputation: 29454
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.
Upvotes: 3
Reputation: 2529
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));
Upvotes: 127
Reputation: 12949
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.
Upvotes: 49
Reputation: 3147
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));
Upvotes: 55
Reputation: 2670
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!
Upvotes: 3