How to modify drawables programmatically on Android?

Grzegorz Matyszczak
3 min readAug 26, 2018

--

Photo by Mounzer Awad on Unsplash

Welcome to my problem-solving blog series! I will describe here common obstacles, which you can face while developing Android apps, and try to give you simple solutions to overcome these difficulties.

Problem

Let’s say we would like to create a simple app which displays a list of colors. Each item in that list contains a name on the left and a little circle with that color on the right. To tweak it a little bit, we want our color to be displayed as a gradient. Sounds simple, right? So we start with creating a RecyclerView, Adapter then a ViewHolder which will bind our entity, e.g. ColorItem. We could end up having a code like this in our ViewHolder:

And our background drawable resource would look like this:

What could possibly go wrong? Let’s build it and run.

Wait, something’s not right! All drawables have the background color of the last bound item, even though I bind the correct one for each item in the ViewHolder.

Solution

To understand what happened here, we need to know one thing about Drawable on Android. Whenever we create a View which has a background set to a resource Drawable, it will create a new Drawable instance, but they all share common state! It’s due to optimizations, to not create e.g. a bitmap for every single view that uses this resource. If you want to read more about it, here is a great blog post explaining everything.

Okay, so we know already what’s causing our problem. Now, what can we do to solve it? Luckily for us, there’s a simple method that we can use to tell Drawable to have its own state and not to share it with other Drawable instances. It’s called Drawable.mutate() and you can read more about it in the documentation.

Here’s the updated code:

Let’s build and run it.

Success! That’s the result we were expecting. Since we are using Kotlin here, we can create a nice looking DSL for Drawable mutations. So the final version of our code would look like this:

Conclusion

We need to remember about these pitfalls of Android framework optimizations when modifying our Drawable objects programmatically. Otherwise, it can lead to unpredictable behaviors, like the one we saw above. Hopefully, I saved you some time on googling and wondering what’s wrong with your code. I’m looking forward to your feedback and wait patiently for the next posts in my problem-solving blog series! :)

--

--