設定drawables物件背景導致資源被影響

BinaryKNight01發表於2017-08-30

相信大家在開發中,經常會動態改變控制元件的顏色,但對於改變drawable下背景的背景色該如何修改呢,修改後又會帶來什麼問題呢,請大家帶著疑問細細看來:

先上程式碼,在drawable下修改背景:

	GradientDrawable p = (GradientDrawable) tv_check_insurance_vin.getBackground().mutate();
        p.setColor(Color.parseColor("#3D5B96"));

程式碼很簡單,就兩行便解決了我們的問題,但不知道你會不會發現這麼修改後,會導致其他介面這個drawable的顏色也會跟著改變,這讓我們有的找不到原因,先不要著急,解決辦法很簡單:

修改程式碼:

	GradientDrawable p = (GradientDrawable) tv_check_insurance_vin.getBackground().mutate();
        p.setColor(Color.parseColor("#3D5B96"));

同理     一個控制元件改變背景色也可以這麼操作 tv.getBackground().mutate().setAlpha(0);

當然也有其他方案,只要在ondestroy改變回你自己顏色就可以了。

問題解決了,那我們來分析下造成這樣的原因吧:

Drawables允許你不需要繼承就可以很容易的定製widgets渲染。事實是,android的應用程式和widgets是使用該drawable物件的,在android的核心框架

中大約有700個drwables被使用。。正式以為他是如此廣泛的被使用,Android對它進行了優化。例如,每一次你建立一個按鈕時,一個新的drawable就會

被裝載。這就意味著應用程式中所有的使用不同drawablesd物件實現不同背景的按鈕,所有的drawables物件公用一個公用的狀態,我們成“constant

state”,這個狀態的內如根據你使用的不同drawables物件而不同,但是它通常包括一個資源所有的屬性。以按鈕為例,常態包括一個點陣圖。如此一所

有按鈕就可以共享一張點陣圖。這將會節省很多的資源。

下面的圖介紹了你設定一張圖給兩個不同View作為背景的建立過程。正如你所看到的那樣,兩個drawables被建立,但是共享公共的部分也就是同一張點陣圖。


這種狀態分享特點極大避免了浪費記憶體,但是當你試圖去修改drawable的屬性時它會導致一些問題。導致背景色錯落。

這種結果能夠用上面的“常態”來解釋。因為我們從一個list item中獲取一個drawable物件時,constant state是一樣的,對BitmapDrawable來說,

透明值就是一個常態,因此,改變一個drawable物件例項的透明值來說,會改變所有其他物件的透明值,更糟糕是,這種問題在1.1和1.0的是不好解決的。

在1.5或者更好的裝置上通過mutate()方法是很容易解決上述問題。當你對一個drawable物件呼叫這個方法時,drawable物件就會被複制而不會印象其他物件。

記住bitmap物件依舊是被重用的,即使是實用mutate(),下面這幅圖說明呼叫mutate()物件之後情況


只要呼叫了鏈式上的mutate方法,問題也就解決了。

相關文章