Android使用Tint為圖標(biāo)Icon動(dòng)態(tài)著色的操作方法
1. 背景
在 App 當(dāng)中,會(huì)有很多 形狀相同、顏色不同 的 Icon。

例如上圖這個(gè)場景,是篩選項(xiàng)的 icon,對(duì)應(yīng)的代碼可能為:
- Xml 中初始化顏色為黑色
<ImageView
...
android:src="@drawable/icon_filter_black" />
- 代碼中根據(jù)篩選狀態(tài),切換不同顏色的 icon
// XXXFragment.kt
imageView.setImageDrawable(
if (isSelect) {
// 篩選后為橙色
resources.getDrawable(R.drawable.icon_filter_orange);
} else {
// 未篩選為黑色
resources.getDrawable(R.drawable.icon_filter_black);
}
)
如果為每種顏色的 Icon 都保存一張圖片,會(huì)增加包體積。同時(shí),會(huì)增加設(shè)計(jì)的工作負(fù)擔(dān)。有沒有什么辦法可以做到只需要一張圖片,然后動(dòng)態(tài)的著色呢?
2. 使用 Tint 動(dòng)態(tài)著色
2.1 使用方式
有以下幾種方式:
- xml 中設(shè)置
<ImageView
...
android:src="@drawable/icon_filter"
app:tint="@color/black"
/>
- 代碼中為 ImageView 設(shè)置
imageView.imageTintList = ColorStateList(...)
- 代碼中直接為 Drawable 設(shè)置
val drawable = resources.getDrawable(R.drawable.icon_filter) drawable.setTint = Color.BLACK imageView.setImageDrawable(drawable)
設(shè)置 tint 后,繪制時(shí)就會(huì)用 tint 的顏色渲染 icon。這樣,就算只有一張圖片,也可以渲染為多種顏色。很大程度的節(jié)省了包體積。
2.2 原理分析
- ImageView 會(huì)將 Tint 傳給 Drawable
// ImageView.java
public void setImageTintList(@Nullable ColorStateList tint) {
mDrawableTintList = tint;
mHasDrawableTint = true;
applyImageTint();
}
private void applyImageTint() {
if (mDrawable != null && (mHasDrawableTint || mHasDrawableBlendMode)) {
mDrawable = mDrawable.mutate();
if (mHasDrawableTint) {
mDrawable.setTintList(mDrawableTintList); // 將 tint 傳遞給 Drawable!
}
// ...
}
}
- Drawable 在 收到 Tint 時(shí)會(huì)創(chuàng)建 ColorFilter,在 draw 時(shí)會(huì)用它做顏色過濾處理。這里拿 VectorDrawable 舉例:
public class VectorDrawable extends Drawable {
private BlendModeColorFilter mBlendModeColorFilter ;
@Override
public void setTintList(ColorStateList tint) {
// 使用 tint 創(chuàng)建 ColorFilter
updateColorFilters(... , tint) ;
}
private void updateColorFilters(@Nullable BlendMode blendMode , ColorStateList tint) {
// ...
mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter , tint , blendMode) ;
}
@Override
public void draw(Canvas canvas) {
// 繪制時(shí),如果外部沒有設(shè)置 mColorFilter,則使用 mBlendModeColorFilter
final ColorFilter colorFilter = (mColorFilter == null ? mBlendModeColorFilter : mColorFilter) ;
// ...
}
}
public abstract class Drawable {
@Nullable
BlendModeColorFilter updateBlendModeFilter(@Nullable ColorStateList tint , ... ) {
// ...
final int color = tint.getColorForState(getState() , Color.TRANSPARENT) ;
if (blendFilter == null || blendFilter.getColor() != color
|| blendFilter.getMode() != blendMode) {
return new BlendModeColorFilter(color , blendMode) ;
}
return blendFilter ;
}
}
3. 注意事項(xiàng)
3.1 同時(shí)設(shè)置 ImageView 與 Drawable,Drawable 的設(shè)置會(huì)失效
- 例如,我們?cè)?xml 中設(shè)置 tint 為黑色
<ImageView
...
android:src="@drawable/icon_filter"
app:tint="@color/black"
/>
- 在代碼中,為 Drawable 設(shè)置為黃色
val drawable = resources.getDrawable(R.drawable.icon_filter) drawable.setTint = Color.YELLOW imageView.setImageDrawable(drawable)
- 此時(shí),對(duì) Drawable 的設(shè)置是不生效的,因?yàn)榇藭r(shí) ImageView.setImageDrawable 會(huì)覆蓋掉 Drawable 自身的 tint
// ImageView.kt
public void setImageDrawable(@Nullable Drawable drawable) {
updateDrawable(drawable) ;
}
private void updateDrawable(Drawable d) {
applyImageTint() ;
}
private void applyImageTint() {
if (mHasDrawableTint) {
mDrawable.setTintList(mDrawableTintList) ;
}
}
- 所以如果同時(shí)設(shè)置 ImageView 與 Drawable 的 tint,要關(guān)注覆蓋問題。
到此這篇關(guān)于Android使用Tint為圖標(biāo)Icon動(dòng)態(tài)著色的操作方法的文章就介紹到這了,更多相關(guān)Android Tint為Icon動(dòng)態(tài)著色內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)網(wǎng)絡(luò)訪問攔截器的常見方式
這篇文章主要為大家詳細(xì)介紹了基于Android實(shí)現(xiàn)網(wǎng)絡(luò)訪問攔截器的幾種常見方式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-07-07
Android點(diǎn)擊WebView實(shí)現(xiàn)圖片縮放及滑動(dòng)瀏覽效果
這篇文章主要為大家詳細(xì)介紹了Android點(diǎn)擊WebView實(shí)現(xiàn)圖片縮放及滑動(dòng)瀏覽效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
Android 仿高德地圖可拉伸的BottomSheet的示例代碼
這篇文章主要介紹了Android 仿高德地圖可拉伸的BottomSheet的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07
Android中轉(zhuǎn)場動(dòng)畫的實(shí)現(xiàn)與兼容性處理
大家都知道Android 中的動(dòng)畫有很多,除了在一個(gè)界面上使用幀動(dòng)畫、屬性動(dòng)畫將一個(gè)或多個(gè) View 進(jìn)行動(dòng)畫處理以外,還可以用于兩個(gè)界面之間過渡、跳轉(zhuǎn)。本文的內(nèi)容包括:Android 5.0+ 的轉(zhuǎn)場動(dòng)畫和Android 4.X 模擬實(shí)現(xiàn) Android 5.0+ 轉(zhuǎn)場效果。有需要的可以參考借鑒。2016-10-10
Activity透明/半透明效果的設(shè)置transparent(兩種實(shí)現(xiàn)方法)
兩種方法實(shí)現(xiàn)Activity透明/半透明效果的設(shè)置,代碼思路很有調(diào)理,感興趣的朋友可以參考下,希望本文可以幫助到你2013-02-02
Ubuntu Android源碼以及內(nèi)核下載與編譯
本文主要介紹Android源碼的下載和編譯,這里整理了相關(guān)資料及如何下載和編譯的詳細(xì)步驟,有需要的小伙伴可以參考下2016-09-09
Android 讓自定義TextView的drawableLeft與文本一起居中
本文主要介紹Android 自定義控件TextView顯示居中問題,在開發(fā)過程中經(jīng)常會(huì)遇到控件的重寫,這里主要介紹TextView的drawableLeft與文本一起居中的問題2016-07-07
Android實(shí)現(xiàn)圖片浮動(dòng)隨意拖拽效果
這篇文章主要介紹了Android的圖片在界面隨意拖動(dòng)的功能,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考,一起跟隨小編過來看看吧2018-04-04

