Drawable共享状态问题

结论: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-1的background

--

View-2的background

可以看到,这个两个view的background对象,确实是两个不同的对象,但是他们的mGradientState,是同一个GradientState对象,这里发生了复用。

所以,在动态修改drawable的颜色(或者GradientState中其他属性)时,需要将改该drawable设置为mutate状态,即调用mutate()方法,该方法会为drawable创建新的mGradientState(Drawable的各派生类实现有所不同)。举例如下:GradientDrawable.mutate()方法如下:


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)
            }
        }
    }

你可能感兴趣的:(Drawable共享状态问题)