cubesoft
cubesoft

Reputation: 3550

Android Drawable wrapper so that that I can change the drawable in all views by replacing in wrapper

Is there a class like Drawable Wrapper? The use case is as follows. I have a layout where many views have background set to a Drawable object. Now I want to replace this Drawable with new one in all the views but I don't want to touch all the views and update their backround manually. Instead I would like to only swap the drawable in this wrapper object and call invalidate on the entire hierarchy.

Upvotes: 0

Views: 246

Answers (1)

Sergei Kozelko
Sergei Kozelko

Reputation: 833

A LayerDrawable can act as a wrapper, though you will need to set it to every view manually at first and I couldn't get it to work without calling invalidate on every view.

To create it you can

  1. Create it manually
val initial = your_initial_drawable
val wrapper = LayerDrawable(arrayOf(initial))
wrapper.setId(0, R.id.layer_id)
  1. Inflate from xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/layer_id">
        initial drawable here
    </item>
</layer-list>
val wrapper = AppCompatResources.getDrawable(this, R.drawable.wrapper) as? LayerDrawable

Then you can change the drawable with setDrawableByLayerId:

wrapper.setDrawableByLayerId(R.id.layer_id, your_new_drawable)

If your minSdk is 23+, then you can skip the layer id and just use setDrawable which operates with layer indexes.

Finally, as I noted in the beginning, it won't work without invalidating the views. That's because changing the drawable doesn't invalidate the view by itself. So depending on your definition of "call invalidate on the entire hierarchy" this will or will not work. Just storing all views in an array and updating them in a loop might be an easier solution instead.

Upvotes: 1

Related Questions