Dynamically changing SVG colours on Android

Recently, I needed to change the colour of part of a drawable — and I wanted to do it better than manually swapping out the whole image, or swapping in and out the changing part and overlaying this on top of a base image.

I knew I wanted the assets to be vector based if at all possible — SVG support was added in Lollipop with the VectorDrawable class and have been a great addition. Assets appear beautifully sharp, and gone are the days of adding multiple pngs to cater for different screen sizes.

I found that with custom attributes and themes, doing what I wanted could be achieved relatively easily.

Changing bauble colours on a Christmas tree

First, we create attributes for the two kinds of bauble, so we can change their colours:

Then, in the VectorDrawable, set the parts we want to dynamically change to use these attributes:

Create themes and set the colours you want to use:

Use the drawable in an ImageView:

That’s it! When you want to change the colours, simply set a different theme and your drawable will update.

See the GitHub repo for a full sample.

Update: If you specify each attribute within a different theme, you can also choose which to apply at runtime by creating a Theme dynamically. This is useful when you know at compile time what colours a certain element are, but don’t know until runtime which need to be updated.

Creating a Theme programmatically and applying required styles

Note: for every different part of your image you want to change, you need a different attribute — so if you happen to have an SVG made up of lots and lots of elements, and you want to change them all separately, this is probably not the best solution for you.

Additionally, this is v21+ only — the backwards compatibility support for VectorDrawables before 21 creates static pngs, so changing the theme at runtime will have no effect.


Special thanks to Mark Allison for the idea and the creator of the Christmas tree SVG used.

If you enjoyed reading this post, you can find me on twitter @emmaguy