Android paint by colour
Theming vector drawables with colour palettes
Vector drawables. The benefits are many, and whilst vector support on Android is still maturing they have a certain characteristic that came in very handy on a recent project: the ability to define shape colours as attribute references that resolve to colour resources.
What..? Let me explain.
In this particular project users could compete to collect a deck of virtual cards belonging to 12 different categories. To make the app’s UI more dynamic we decided to colour screens based on the category of the card being viewed, but we wanted to avoid creating 12 near identical assets every time a new screen or piece of artwork was added.
Ideally we wanted to define our 12 colour palettes once and then create a single vector drawable for each piece of artwork in the app. This would allow us to tune the colour palettes without having to update all of the artwork assets. Referencing colour attributes instead of hardcoding hex values inside the vector drawable xml allows us to do exactly that!
Defining the colour palettes
The first step is to define a colour palette styleable. This contains the colour swatches available in the palette.
Then, in the android:fillColor attributes of the paths inside our vector drawables simply reference the colour attributes defined in that styleable.
Unfortunately, from within Android Studio’s preview window we won’t be able to render the drawable yet as there is nothing telling it which colours to use for each of the palette swatches. We do that by creating a Theme for each palette and filling in the swatches with colours or colour references.
Now, if we preview a layout containing a vector drawable and set the appropriate theme we’ll see the vector coloured with the appropriate palette. Voilà!
Applying palettes to screens
As the colour palettes are just Android themes, to apply them just set the appropriate themes for activities in XML or, if the decision is made at runtime, call setTheme in the activity before any views are created with the context.
Now, to tweak a category’s colours we only have to update the colours inside a palette and the changes will be reflected in all of the artwork throughout the app without having to update the actual assets. It also makes it super easy to add a new card category, we just have to create a new colour palette. Less work for the dev, less work for the designer. Happy team.
Applying palettes to individual drawables
Finally, considering it was an adversarial game there were times when we presented two battling cards on the same screen and this meant we couldn’t just theme the entire activity. Some assets needed to be coloured with one palette, and others with a different one.
ContextThemeWrapper to the rescue!
Good, but not great…
Actually, they are great. But they could get better. I’m still trying to figure out a way to programmatically set the colour of the shapes within vector drawables. That would allow a palette to be dynamically generated from an image using the Support v7 graphics Palette API and applied to the surrounding artwork.
Still, vector drawable support is relatively new, only being natively supported on API level 21+, so I’m sure we can expect a greater degree of control in coming versions. Already they’re reducing the workload on designers providing assets, reducing the effort by developers when updating assets, and slimming down APK sizes. Use them.