英文:
Android Drawable wrapper so that that I can change the drawable in all views by replacing in wrapper
问题
有没有类似的可绘制包装器?使用案例如下:我有一个布局,其中许多视图的背景都设置为Drawable对象。现在我想在所有视图中将这个Drawable替换为新的Drawable,但我不想触及所有视图并手动更新它们的背景。相反,我只想在这个包装器对象中交换可绘制对象并对整个层次结构调用invalidate。
英文:
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.
答案1
得分: 1
LayerDrawable
可以充当包装器,但是起初你需要为每个视图手动设置它,并且我在不调用每个视图上的invalidate
的情况下无法使其工作。
要创建它,你可以:
- 手动创建
val initial = 你的初始可绘制对象
val wrapper = LayerDrawable(arrayOf(initial))
wrapper.setId(0, R.id.layer_id)
- 从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">
初始的可绘制对象
</item>
</layer-list>
val wrapper = AppCompatResources.getDrawable(this, R.drawable.wrapper) as? LayerDrawable
然后,你可以使用setDrawableByLayerId
来更改可绘制对象:
wrapper.setDrawableByLayerId(R.id.layer_id, 你的新可绘制对象)
如果你的minSdk
是23+,那么你可以跳过层ID,直接使用setDrawable
,它操作的是层索引。
最后,正如我在开始时指出的,不调用视图上的invalidate
是不起作用的。这是因为仅仅改变可绘制对象本身并不会使视图无效。因此,根据你对“在整个层次结构上调用invalidate”定义的方式,这可能起作用,也可能不起作用。只需将所有视图存储在数组中,并在循环中更新它们可能是一个更简单的解决方案。
英文:
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
- Create it manually
val initial = your_initial_drawable
val wrapper = LayerDrawable(arrayOf(initial))
wrapper.setId(0, R.id.layer_id)
- 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论