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

huangapple go评论132阅读模式
英文:

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的情况下无法使其工作。

要创建它,你可以:

  1. 手动创建
val initial = 你的初始可绘制对象
val wrapper = LayerDrawable(arrayOf(initial))
wrapper.setId(0, R.id.layer_id)
  1. 从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

  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
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;layer-list xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
    &lt;item android:id=&quot;@+id/layer_id&quot;&gt;
        initial drawable here
    &lt;/item&gt;
&lt;/layer-list&gt;
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.

huangapple
  • 本文由 发表于 2023年3月10日 01:15:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75687927.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定