Tips for DrawableCompat.setTint() Under API 21

To change image and icon’s color, we used to call Drawable.setColorFilter (int color, PorterDuff.Mode.SRC_ATOP) with color what we wanted. After DrawableCompat released setTint(Drawable drawable, 
 int tint)
, we change to use DrawableCompat to change tint color.
  • DrawableCompat.wrap(Drawable drawable)

To make DrawableCompat.setTint(Drawable, int) work update API 21, we need to wrap original drawable.

Drawable drawable = ContextCompat.getDrawable(context, R.drawable.xxx);
Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(wrappedDrawable, ContextCompat.getColor(context, R.color.white));
  • Drawable.mutate()

Since Android optimized performance, by default, all drawables instances loaded from the same resource share a common state. When we modify the state of one instance, all the other instances will receive the same modification. So if we want not to affect other drawables, don’t forget to mutate the drawable via Drawable.mutate() before applying the filter. A mutable drawable is guaranteed to not share its state with any other drawables.

Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
Drawable mutableDrawable = wrappedDrawable.mutate();
DrawableCompat.setTint(mutableDrawable, ContextCompat.getColor(context, R.color.white));
  • Drawable.invalidateSelf()

And for some devices, this still not worked. So you might need to call Drawable.invalidateSelf() to make drawable update.