结论:android中从同一个资源文件中加载出来的drawable会共享状态,如果有加载出来多个drawable的实例对象,当改变了其中一个的状态时,其他drawable的状态也会相应改变。
实例:在修改一个view,或者它的background,即时是新创建的view对象,如果它是从同一个xml中加载出来的(包括矢量图、shape等),在代码中动态修改的它颜色,会影响到其他从该xml加载出的view。这是因为它的mGradientState是被复用的。
下面两个图,是从同一个xml中加载的view对象(在recyclerView的两个item中),在动态改变了第二个view的background颜色后,如果第一个view所在的item重新bind,新创建出的view,也表现出和原来第二个view同样的背景颜色。修改颜色的方法如下:
private fun changeBackgroundColor(@ColorInt argb: Int?) {
argb?.let {
if (mRootView?.background is GradientDrawable) {
val grad: GradientDrawable = mRootView?.background as GradientDrawable
grad.setColor(argb)
}
}
}
--
可以看到,这个两个view的background对象,确实是两个不同的对象,但是他们的mGradientState,是同一个GradientState对象,这里发生了复用。
所以,在动态修改drawable的颜色(或者GradientState中其他属性)时,需要将改该drawable设置为mutate状态,即调用mutate()方法,该方法会为drawable创建新的mGradientState(Drawable的各派生类实现有所不同)。举例如下:GradientDrawable.mutate()方法如下:
所以需要将上述修改背景颜色的方法,修改如下:
private fun changeBackgroundColor(@ColorInt argb: Int?) {
argb?.let {
if (mRootView?.background is GradientDrawable) {
val grad: GradientDrawable = (mRootView?.background as GradientDrawable).mutate() as GradientDrawable
grad.setColor(argb)
}
}
}