I've recently updated my phone to Android Marshmallow and ran my existing app on it, but noticed a difference in color behavior: When applying changes to the background of a view (drawable), all views that share the same background (reference) will also the same changes applied. While previously, this was not the case.
Example
In this example, I have a two views with the same background color, and I want to change the alpha level of one of both views.
First we define the views in the layout:
<LinearLayout
android:id="@+id/test1"
android:orientation="horizontal"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@color/testColor2">
</LinearLayout>
<LinearLayout
android:id="@+id/test2"
android:orientation="horizontal"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@color/testColor1"
android:layout_marginLeft="5dp">
</LinearLayout>
Both views share the same background color or drawable:
<color name="testColor1">#3F51B5</color>
<color name="testColor2">#3F51B5</color>
The result looks like this:
Now we are going to change one of the two background, like this:
LinearLayout test1 = (LinearLayout) findViewById(R.id.test1);
LinearLayout test2 = (LinearLayout) findViewById(R.id.test2);
test1.getBackground().setAlpha(80);
Which results in this:
However, the desired and expected result is obviously this:
Download the sample project here.
A few thoughs:
Question
How can I make changes to a view's background without this affecting other views that share the same background. Preferably while still being able to use a background that directly refers to a color defined in the color's xml file
Use app:drawableTint="@color/yourColor" in the xml instade android:drawableTint="@color/yourColor" . It has the backward compatibility.
android.graphics.drawable.ColorDrawable. A specialized Drawable that fills the Canvas with a specified color. Note that a ColorDrawable ignores the ColorFilter. It can be defined in an XML file with the <color> element.
To set Android Button background color, we can assign android:backgroundTint XML attribute for Button in layout file with the required Color Value. To programmatically set or change Android Button background color, we may call pass the method Button.
Most likely the class of each view's background and constantstate are the same object. It seems as if the two color resources have been "merged" somewhere -- meaning they have shared ConstantState. Maybe in the Resources class' caching? I would've expected them to stay separate since they're different resources (albeit with the same color value), but apparently not.
– Snild Dolkow
The ColorDrawable's state stores alpha, so any changes to one will change the others. To prevent this, you can first call mutate() on the drawable, separating the two drawables (by making a copy of the state).
In the example, this would result in using test1.getBackground().mutate().setAlpha(80);
instead of directly applying the alpha.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With