lannyf lannyf - 2 months ago 15
Android Question

Is drawable a singleton

Got a behavior not sure if it is as it should be.
If the drawable used in the view's background IS one instance shared with other views, how to change the individual's color?

having R.drawable.circle_shape as:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<corners android:radius="10dip"/>
<solid android:color="#cccccc"/>
</shape>


used as two instances in one fragment

<ImageView
android:id="@+id/circle_1”
android:layout_width="22dp"
android:layout_height="22dp"
android:gravity="center"
android:layout_gravity="center"
android:background="@drawable/circle_shape"
android:shadowRadius="10.0"
/>

<ImageView
android:id="@+id/circle_2”
android:layout_width="22dp"
android:layout_height="22dp"
android:gravity="center"
android:layout_gravity="center"
android:background="@drawable/circle_shape"
android:shadowRadius="10.0"
/>


the other use is for the list item’s template in other fragment

<ImageView
android:id="@+id/listItem_image”
android:layout_width="22dp"
android:layout_height="22dp"
android:gravity="center"
android:layout_gravity="center"
android:background="@drawable/circle_shape"
android:shadowRadius="10.0"
/>


when I change the circle color for the instance c1, I noticed that c2 and listItem_image changes color too.

View c1 = (View) findViewById(R.id. circle_1);
c1.setBackgroundResource(R.drawable.circle_shape); // with or without this it will still affect the other ImageView which also uses R.drawable.circle_shape as background

((GradientDrawable) c1.getBackground()).setColor(intColor);
((GradientDrawable) c1.getBackground()).setStroke(0, Color.TRANSPARENT);

Answer

Not really a singleton, but your guess is in the right direction. When you get a drawable, it shares state with other drawables. That's why when you modify one of them, you modify all the drawables which share state with it.

What you need to do is mutate drawable so that a new state is created. In your case it will look something like this:

GradientDrawable drawable = ((GradientDrawable) c1.getBackground()).mutate();
drawable.setColor(intColor);
drawable.setStroke(0, Color.TRANSPARENT);

The first line creates a new state, which allows the next two lines to change only the state of this particular drawable.