Android中使用背景色Alpha值遇到的一個(gè)坑
前言
Android通過(guò)設(shè)置Alpha值圖片淡化、透明度大家應(yīng)該都知道,下面是段簡(jiǎn)單的示例代碼:
View v = findViewById(R.id.img_layout); v.getBackground().setAlpha(77);// 設(shè)置背景圖片透明度;0~255透明度值
以上是個(gè)簡(jiǎn)單的介紹,但本文介紹的是公司項(xiàng)目一個(gè)留了很久的 bug,嘗試找了很多次原因都沒有頭緒。
這個(gè) bug 是這樣的:
定義了一個(gè)主題色為例如 #FF0000,很多界面控件都用了這個(gè)顏色??墒沁@個(gè)顏色在 app 使用過(guò)程中用著用著就會(huì)出現(xiàn)變成了透明的情況,而且出現(xiàn)透明之后,所有使用這個(gè)顏色的控件都會(huì)變成透明。
更奇怪的是,重啟應(yīng)用會(huì)恢復(fù)這個(gè)問(wèn)題,但是操作一會(huì)兒又會(huì)出現(xiàn)。
項(xiàng)目有個(gè)隨著頁(yè)面滾動(dòng)標(biāo)題欄從透明過(guò)渡到主題色的界面實(shí)現(xiàn),類似于 Design 庫(kù)中 AppBar 的那種效果。實(shí)現(xiàn)方法是這樣的:
// 滾動(dòng)監(jiān)聽器 偽代碼 someParams -> { //... view.getBackground().setAlpha(percent); //... }
今天「代碼級(jí)復(fù)用」這一 feature 時(shí),發(fā)現(xiàn)把 bug 也引入了新項(xiàng)目,才發(fā)現(xiàn)這個(gè)實(shí)現(xiàn)的問(wèn)題之所在……
首先,view.getBackground()
獲得的是一個(gè) ColorDrawable,然后給這個(gè) ColorDrawable 設(shè)置 Alpha 值的話,會(huì)影響所有設(shè)置 background 為這個(gè)顏色的背景色的 Alpha 值。
然后就寫了個(gè)小 demo 驗(yàn)證了一下這個(gè)說(shuō)法,雖然不是立即生效的,然后返回退出應(yīng)用后,兩個(gè)相同顏色背景的 view,改變其中一個(gè)確實(shí)會(huì)影響到另一個(gè)。
當(dāng)時(shí)反應(yīng)就是:WTF?難不成全局的相同顏色的 Drawable 都是同一個(gè)對(duì)象?不過(guò)很快打印了一下 background 的 drawable 對(duì)象驗(yàn)證了并不是這樣——雖然這些 view 獲得的 ColorDrawable 的 Alpha 值都相同,但 hashcode 都是不同的。
所以我更傾向于這是 Android 內(nèi)存優(yōu)化帶來(lái)的 bug,即使這個(gè)顏色在定義時(shí)就有 Alpha 值,在修改后也會(huì)被忽略,并影響到其他的 view。該問(wèn)題只在布局文件里設(shè)置 background 為一個(gè) color 的 id 或者值,或者 setBackgroundResource 為一個(gè) color 時(shí)存在。如果使用 new ColorDrawable(int)
來(lái)構(gòu)造一個(gè)使用相同顏色值的對(duì)象則不受影響,我目前也正是使用這個(gè)方法來(lái)躲避掉這個(gè) feature。
UPDATE:
發(fā)現(xiàn)文檔里有這個(gè)方法,驗(yàn)證了之前的說(shuō)法,從同一資源加載的 drawable 確實(shí)會(huì)共享狀態(tài),不過(guò)有一個(gè) mutate 方法來(lái)禁用這一特性。文檔如下:
Drawable mutate ()
Make this drawable mutable. This operation cannot be reversed. A mutable drawable is guaranteed to not share its state with any other drawable. This is especially useful when you need to modify properties of drawables loaded from resources. By default, all drawables instances loaded from the same resource share a common state; if you modify the state of one instance, all the other instances will receive the same modification. Calling this method on a mutable Drawable will have no effect.
翻譯:
Drawable mutate ()
讓一個(gè) Drawable 變?yōu)?mutable 的。這個(gè)操作是不可逆的。一個(gè) mutable 的 drawable 可以保證不會(huì)分享自己的狀態(tài)給其他 drawable。當(dāng)一個(gè) drawable 是從 resource 加載的,在需要更改它狀態(tài)時(shí)這個(gè)方法特別有用。在默認(rèn)情況下,所有從相同 resource 的 drawable 的實(shí)例是共享一個(gè)通用狀態(tài)的;如果你修改了其中一個(gè)的狀態(tài),所有其他的實(shí)例也會(huì)收到相同的改動(dòng)。在一個(gè)已經(jīng)是可變的 drawable 上調(diào)用該方法沒有效果。
所以,上述代碼只要在 drawable 獲取之后,調(diào)用一下 mutate()
方法即可。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Android中替換WebView加載網(wǎng)頁(yè)失敗時(shí)的頁(yè)面
這篇文章主要介紹了Android中替換WebView加載網(wǎng)頁(yè)失敗時(shí)的頁(yè)面,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-01-01Android無(wú)障礙自動(dòng)化結(jié)合opencv實(shí)現(xiàn)支付寶能量自動(dòng)收集操作方法
opencv可以進(jìn)行圖像識(shí)別,兩者結(jié)合在一起即可實(shí)現(xiàn)支付寶能量自動(dòng)收集,opencv用于識(shí)別能量,無(wú)障礙服務(wù)用于模擬手勢(shì),即點(diǎn)擊能量,這篇文章主要介紹了Android無(wú)障礙自動(dòng)化結(jié)合opencv實(shí)現(xiàn)支付寶能量自動(dòng)收集,需要的朋友可以參考下2024-07-07Kotlin協(xié)程開發(fā)之Flow的融合與Channel容量及溢出策略介紹
這篇文章主要介紹了Kotlin協(xié)程:Flow的融合、Channel容量、溢出策略,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09Android編程實(shí)現(xiàn)的簡(jiǎn)易路徑導(dǎo)航條功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)的簡(jiǎn)易路徑導(dǎo)航條功能,結(jié)合實(shí)例形式分析了Android結(jié)合視圖、布局及路徑操作實(shí)現(xiàn)導(dǎo)航條功能的相關(guān)技巧,需要的朋友可以參考下2017-01-01Kotlin開發(fā)實(shí)戰(zhàn)之hello world
這篇文章主要為大家詳細(xì)介紹了Kotlin開發(fā)實(shí)戰(zhàn)之hello world的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05Android開發(fā)應(yīng)用第一步 安裝及配置模擬器Genymotion
這篇文章主要介紹了Android開發(fā)應(yīng)用第一步,即安裝及配置模擬器Genymotion,感興趣的小伙伴們可以參考一下2015-12-12Android Spinner 組件的應(yīng)用實(shí)例
這篇文章主要介紹了Android Spinner 組件的應(yīng)用實(shí)例的相關(guān)資料,希望通過(guò)本文大家能夠掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09Android自定義帶進(jìn)度條WebView仿微信加載過(guò)程
這篇文章主要為大家詳細(xì)介紹了Android自定義帶進(jìn)度條WebView仿微信加載過(guò)程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03Android 實(shí)現(xiàn)無(wú)網(wǎng)絡(luò)頁(yè)面切換的示例代碼
本篇文章主要介紹了Android 實(shí)現(xiàn)無(wú)網(wǎng)絡(luò)頁(yè)面切換的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09Android開發(fā)Jetpack組件ViewModel使用講解
這篇文章主要介紹了Android?Jetpack架構(gòu)組件?ViewModel詳解,ViewModel類讓數(shù)據(jù)可在發(fā)生屏幕旋轉(zhuǎn)等配置更改后繼續(xù)存在,ViewModel類旨在以注重生命周期的方式存儲(chǔ)和管理界面相關(guān)的數(shù)據(jù),感興趣可以來(lái)學(xué)習(xí)一下2022-08-08