Android 運(yùn)行時改變 Drawable 的填充色[Toast 樣式的進(jìn)階版]
這兩天無聊,整了
Toast的樣式庫
先貼地址: https://github.com/didikee/UIToast
1. 關(guān)于 Toast 樣式的修改
參見我上一篇文章:更換 Android 原生 Toast 的樣式
2. 運(yùn)行時改變 Drawable 的填充色
以 Toast的背景為例說明, Toast的背景是一個名為 toast_frame.9.png的 點(diǎn)9 png圖,處理完的效果如圖:

Toast 的背景已經(jīng)變?yōu)?colorPrimaryDark的顏色.
實(shí)現(xiàn)是利用 Android Tint(翻譯為: 著色),Android 5.0以上默認(rèn)支持的,為了兼容,我們使用 Android Support V4 的包中提供了 DrawableCompat類,輔助我們?yōu)?Drawable 著色:
public static Drawable tintDrawable(Drawable drawable, ColorStateList colors) {
final Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTintList(wrappedDrawable, colors);
return wrappedDrawable;
}
這樣已經(jīng)能輕易的實(shí)現(xiàn) Drawable的著色了,但是還沒完,還有一個很重的知識點(diǎn)要說明.也許你在使用了這個方法后你會發(fā)現(xiàn),你調(diào)用系統(tǒng)自帶的 Toast.makeToast(...);方法背景也變成了之前的顏色而不是默認(rèn)的暗黑色.
這是因?yàn)?Android 為了優(yōu)化系統(tǒng)性能,資源 Drawable 只有一份拷貝,你修改了它,等于所有的都修改了.也就是說同一份資源的狀態(tài)(比如pressed 等)是共享的.不過, Drawable 提供了一個方法 mutate(),來打破這種共享狀態(tài),等于就是要告訴系統(tǒng),我要修改(mutate)這個 Drawable.
當(dāng)然,Android 系統(tǒng)只是儲存了一份 Drawable 的狀態(tài)值,而非緩存整個 Drawable,所以不必?fù)?dān)心性能問題.
實(shí)際應(yīng)用的代碼片段如下:
Drawable toastBackgroundDrawable = TintDrawableUtil.tintDrawable(
toastView.getBackground().mutate(),//mutate(),設(shè)置為狀態(tài)不共享,以免影響系統(tǒng)默認(rèn)的 Toast背景.
ColorStateList.valueOf(toastBackgroundColor));
3. 下面是介紹我寫的Toast的庫了
包含的功能:
1. 自定義 Toast 字體顏色
2. 自定義 Toast 背景顏色
3. 自定義 Toast 展示位置(類似 Popupwindow 在某某下方(正下方水平居中)展示)
4. 自定義 Toast 進(jìn)出場動畫
以上四種可以混搭,庫比較輕量,三個類,但是依賴 v4包,想想v4已經(jīng)是眾多app必備了我就直接用了.如果有必要的話我可以寫個不需要 v4包的.
地址: https://github.com/didikee/UIToast
參考資料: Drawable 著色的后向兼容方案
在搜索到這篇文章時我覺得我的不用寫了,人家寫的比我好,但是為了記錄也為了把更好的分享給大家,我還是把這篇文章貼在這里,enjoy~