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)
            }
        }
    }
相關文章
相關標籤/搜索