DrawableCompat setTint tints all new Drawables with the same id
Asked Answered
T

1

19

I have chat bubbles which I want to tint in some situations:

Drawable bubbleDrawable = ContextCompat.getDrawable(context, R.drawable.bg_chat_bubble);

if (tint) {
    bubbleDrawable = DrawableCompat.wrap(bubbleDrawable);
    DrawableCompat.setTint(bubbleDrawable, bubbleTint);
}

The problem is that once once that R.drawable.bg_chat_bubble (it is a 9-patch) was tinted then all calls to ContextCompat.getDrawable(context, R.drawable.bg_chat_bubble) returns the tinted image instead of the orignal. Even when I close a chat and open completely different chat, the bubbles there have the previous tint. Only killing the app helps to restore the correct color. Until the first tint...

Even directly setting the bubbleDrawable = ContextCompat.getDrawable(context, R.drawable.bg_chat_bubble) inside the tint branch after calling setTint gives a tinted image instead of the original.

I also tried getResources().getDrawable(R.drawable.bg_chat_bubble) but the result is the same. So once I want to use a tint for any drawable resrouce I must always set a tint for that resource otherwise I get unpredictable results.

This is happening on Android 5.1 (probably also others) and with appcompat-v7:23.2.+ and appcompat-v7:23.1.+. Is this a know bug or I am doing something wrong?

Twosided answered 29/3, 2016 at 9:8 Comment(3)
try to mutate the drawable before setting the tintAdrian
@pksink thank, this works perfectly. but what about memory consumption? make your comment an answer and i will accept it.Twosided
it only creates a new small "common state", so it is not big dealAdrian
A
47

all you need is to mutate your drawable before setting the tint:

bubbleDrawable.mutate()

Drawable.mutate

Make this drawable mutable. This operation cannot be reversed. A mutable drawable is guaranteed to not share its state with any other drawable. This is especially useful when you need to modify properties of drawables loaded from resources. By default, all drawables instances loaded from the same resource share a common state; if you modify the state of one instance, all the other instances will receive the same modification. Calling this method on a mutable Drawable will have no effect.

Adrian answered 29/3, 2016 at 10:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.