In android I have read a few articles on how drawables share a constant state. So if you make a change to a drawable it affects all the same bitmaps. For example lets say you had a list of star drawables. changing the alpha on one will change all the star drawables alpha. but you can use mutate to get your own copy of a drawable with no shared state.
The article I was reading is here
Now onto my question:
What is the difference between the following two calls in android:
Drawable clone = drawable.getConstantState().newDrawable();
// vs
Drawable clone = (Drawable) drawable.getDrawable().mutate();
For me they are both cloning a drawable as they both return a drawable that has no shared state. Am I missing something ?
There are two ways to define and instantiate a Drawable besides using the class constructors: Inflate an image resource (a bitmap file) saved in your project. Inflate an XML resource that defines the drawable properties.
In addition to simple drawing, Drawable provides a number of generic mechanisms for its client to interact with what is being drawn: The setBounds(Rect) method must be called to tell the Drawable where it is drawn and how large it should be.
Drawable. invalidateSelf() will call the view's invalidateDrawable() method, which will invalidate only the current bounds of the drawable. If you aren't moving the drawable around, this will have the same effect as calling invalidate(mDrawable. getBounds()) .
A drawable resource is a general concept for a graphic that can be drawn to the screen and which you can retrieve with APIs such as getDrawable(int) or apply to another XML resource with attributes such as android:drawable and android:icon . There are several different types of drawables: Bitmap File.
So if you make a change to a drawable it affects all the same bitmaps. For example lets say you had a list of star drawables. changing the alpha on one will change all the star drawables alpha. but you can use mutate to get your own copy of a drawable with no shared state. What is the difference between the following two calls in android:
A LayerDrawable is a drawable object that manages an array of other drawables. Each drawable in the list is drawn in the order of the list—the last drawable in the list is drawn on top. Each drawable is represented by an <item> element inside a single <layer-list> element.
The opposite method is newDrawable (). It creates a new drawable but with the same constant state. E.g. look at BitmapDrawable.BitmapState:
Shape drawable. A drawable resource is a general concept for a graphic that can be drawn to the screen and which you can retrieve with APIs such as getDrawable (int) or apply to another XML resource with attributes such as android:drawable and android:icon . There are several different types of drawables:
As @4castle pointed in comments mutate()
method returns same instance of the drawable with copied constant drawable state. Docs says that
A mutable drawable is guaranteed to not share its state with any other drawable
So it is safe to change a drawable without affecting drawables with the same state
Lets play with this drawable - a black shape
<!-- shape.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@android:color/black" />
</shape>
view1.setBackgroundResource(R.drawable.shape); // set black shape as a background
view1.getBackground().mutate().setTint(Color.CYAN); // change black to cyan
view2.setBackgroundResource(R.drawable.shape); // set black shape background to second view
The opposite method is newDrawable()
. It creates a new drawable but with the same constant state. E.g. look at BitmapDrawable.BitmapState
:
@Override
public Drawable newDrawable() {
return new BitmapDrawable(this, null);
}
Changes to new drawable will not affect current drawable, but will change a state:
view1.setBackgroundResource(R.drawable.shape); // set black shape as background
Drawable drawable = view1.getBackground().getConstantState().newDrawable();
drawable.setTint(Color.CYAN); // view still black
view1.setBackground(drawable); // now view is cyan
view2.setBackgroundResource(R.drawable.shape); // second view is cyan also
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