Drawable共享状态问题

Drawable共享状态问题

结论:android中从同一个资源文件中加载出来的drawable会共享状态,若是有加载出来多个drawable的实例对象,当改变了其中一个的状态时,其余drawable的状态也会相应改变。android

实例:在修改一个view,或者它的background,即时是新建立的view对象,若是它是从同一个xml中加载出来的(包括矢量图、shape等),在代码中动态修改的它颜色,会影响到其余从该xml加载出的view。这是由于它的mGradientState是被复用的。ide

​ 下面两个图,是从同一个xml中加载的view对象(在recyclerView的两个item中),在动态改变了第二个view的background颜色后,若是第一个view所在的item从新bind,新建立出的view,也表现出和原来第二个view一样的背景颜色。修改颜色的方法以下:this

private fun changeBackgroundColor(@ColorInt argb: Int?) {
        argb?.let {
            if (mRootView?.background is GradientDrawable) {
                val grad: GradientDrawable = mRootView?.background as GradientDrawable
                grad.setColor(argb)
            }
        }
    }

屏幕快照 2019-09-24 下午4.25.43

屏幕快照 2019-09-24 下午4.27.25

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

​ 而GradientState.setColor方法,修改的正是mGradientState中保存的颜色值。该方法以下,能够看到方法注释里也提醒了咱们会影响全部从同一resource中加载的drawable:code

屏幕快照 2019-09-24 下午5.30.29

​ 因此,在动态修改drawable的颜色(或者GradientState中其余属性)时,须要将改该drawable设置为mutate状态,即调用mutate()方法,该方法会为drawable建立新的mGradientState(Drawable的各派生类实现有所不一样)。GradientDrawable.mutate()方法以下:xml

@Override
    public Drawable mutate() {
        if (!mMutated && super.mutate() == this) {
            mGradientState = new GradientState(mGradientState, null);
            updateLocalState(null);
            mMutated = true;
        }
        return this;
    }

​ 因此须要将上述修改背景颜色的方法,修改以下:对象

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)
            }
        }
    }
相关文章
相关标签/搜索