Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android Drawable - getConstantState.newDrawable() vs mutate()

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 ?

like image 894
j2emanue Avatar asked Dec 15 '16 05:12

j2emanue


People also ask

Which of the following ways defines and instantiates the drawable class?

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.

Which of the following method of the drawable class allow the client to interact with the drawn object?

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.

How do you invalidate drawable?

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()) .

What are Drawables in Android?

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.

What is the difference between mutate and change to a drawable?

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:

What is a layerdrawable in Python?

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.

What is the opposite of newdrawable ()?

The opposite method is newDrawable (). It creates a new drawable but with the same constant state. E.g. look at BitmapDrawable.BitmapState:

What is drawable shape in Android?

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:


1 Answers

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
like image 162
Kirill Avatar answered Oct 02 '22 22:10

Kirill