A short post about how to tint drawables and bitmaps to match the current theme.

When designing the themes section of Ready, we wanted to come up with a way of changing not just the basic color aspects of the app, but the icons and other drawables as well. Using the usual method, this would mean creating a png for each color, and switching between them based on the selected theme - a huge overhead in code, and a also an increase in apk size. We also wanted to make adding colors in the future easy, without having to create new resources each and every time.

DrawableCompat

Google introduced the DrawableCompat class in the v4 support library, which introduces tinting capabilities for pre-Lollipop devices. It has a full-fledged API, even supports tint lists, and mirroring for RTL layouts, but it was a bit heavyweight for our use case, and also you have to wrap the current Drawable with the wrap() method.

Introducing the TintedBitmapDrawable

So we came up with our own implementation, a lightweight BitmapDrawable subclass called TintedBitmapDrawable, with an overridden draw() method taking care of tinting using a LightingColorFilter. It only consists of three functions, so it doesn’t mean a significant increase in the method count. The tint color can be specified in one of the two extra constructors or via the setTint() method.

public final class TintedBitmapDrawable extends BitmapDrawable { private int tint ; private int alpha ; public TintedBitmapDrawable ( final Resources res , final Bitmap bitmap , final int tint ) { super ( res , bitmap ); this . tint = tint ; this . alpha = Color . alpha ( tint ); } public TintedBitmapDrawable ( final Resources res , final int resId , final int tint ) { super ( res , BitmapFactory . decodeResource ( res , resId )); this . tint = tint ; this . alpha = Color . alpha ( tint ); } public void setTint ( final int tint ) { this . tint = tint ; this . alpha = Color . alpha ( tint ); } @Override public void draw ( final Canvas canvas ) { final Paint paint = getPaint (); if ( paint . getColorFilter () == null ) { paint . setColorFilter ( new LightingColorFilter ( tint , 0 )); paint . setAlpha ( alpha ); } super . draw ( canvas ); } }

And this is how to use it:

tintedDrawable = new TintedBitmapDrawable ( resources , R . drawable . ic_arrow_back_white_24dp , Color . GREEN );

Benefits and tips