如何在Android XML中调整vector tintMode图标着色算法?
- 内容介绍
- 相关推荐
本文共计983个文字,预计阅读时间需要4分钟。
低于Android 5.0(API 21)时,使用`tintMode`在XML中直接写在`vector`标签中是不被支持的——系统不会解析它。真正起作用的方法是,通过Java或Kotlin代码调用`DrawableCompat.setTintMode`,或者使用`AppCompatImageView`配合`app:tintMode`属性。
常见错误现象:tintMode="multiply" 写在 src="@drawable/ic_home" 的 vector 文件里,但图标颜色没变,或者只在部分机型上生效。
- Android 5.0+:XML 中的
tintMode在ImageView或AppCompatImageView上才有效,且必须配合tint属性一起用 - Android 4.x:只能靠代码设置,XML 里的
tintMode字段会被静默丢弃 - 如果用了
android:background而非android:src,tint和tintMode全部失效
tintMode 可选值对应哪些混合逻辑?别硬记,看效果反推
Android 支持的 tintMode 实际是 Porter-Duff 混合模式子集,不是 Photoshop 那套。最常踩坑的是把 multiply 当“变暗”,把 screen 当“变亮”,结果发现图标发灰或消失——因为混合对象是 tint 颜色和 vector 原图 alpha 通道,不是 RGB 像素叠加。
关键理解点:vector 图标本质是单色(alpha + 路径),tint 是上色源,tintMode 决定怎么把 tint “叠”到路径的透明度上。
-
tintMode="src_in":最常用,默认行为,tint 颜色只出现在原图不透明区域(安全、兼容性最好) -
tintMode="multiply":适合深色 tint + 浅色 icon,但若原图含半透区域,可能意外变暗甚至发黑 -
tintMode="screen":适合浅色 tint + 深色 icon,但容易过曝,尤其在白色背景上显得发虚 -
tintMode="add":API 29+ 才支持,慎用,部分低端机渲染异常
XML 中正确写法:属性位置和宿主控件有强绑定
不能把 tintMode 直接塞进 vector.xml 的根标签里期望全局生效。它必须由使用方控件驱动,且不同控件支持方式不同。
典型错误:vector.xml 里写 android:tintMode="src_in" —— 这个字段会被 aapt 忽略,毫无作用。
- 在
ImageView中:用android:tint+android:tintMode,仅 API 21+ 有效 - 在
AppCompatImageView中:用app:tint+app:tintMode,向下兼容到 API 14 - 不要在
vector.xml文件中写任何tint或tintMode相关属性 - 如果用
android:background显示 vector,所有 tint 行为都失效,改用android:src
运行时动态切换 tintMode 的兼容写法
想在点击时切 multiply → src_in?别只调 setImageTintMode(),漏掉 setColorFilter() 兼容旧版会出问题。
原因:API 21 以下 ImageView 不支持 tintMode,必须降级为 ColorFilter 手动模拟。
- 统一用
DrawableCompat.wrap(drawable)包装 vector drawable - 再调
DrawableCompat.setTintMode(wrapped, mode)和DrawableCompat.setTint(wrapped, color) - 最后
imageView.setImageDrawable(wrapped),避免直接用setImageTintList()(它不控制 mode) - 特别注意:
setTintMode()必须在setTint()之后调,否则某些 ROM 下 mode 不生效
最易被忽略的一点:vector 的 android:fillColor 如果设成非 #00000000(比如写了具体颜色),就会和 tint 叠加出不可控结果——务必确保原始 vector 中所有 fillColor 是透明或纯黑,把着色完全交给 tint 控制。
本文共计983个文字,预计阅读时间需要4分钟。
低于Android 5.0(API 21)时,使用`tintMode`在XML中直接写在`vector`标签中是不被支持的——系统不会解析它。真正起作用的方法是,通过Java或Kotlin代码调用`DrawableCompat.setTintMode`,或者使用`AppCompatImageView`配合`app:tintMode`属性。
常见错误现象:tintMode="multiply" 写在 src="@drawable/ic_home" 的 vector 文件里,但图标颜色没变,或者只在部分机型上生效。
- Android 5.0+:XML 中的
tintMode在ImageView或AppCompatImageView上才有效,且必须配合tint属性一起用 - Android 4.x:只能靠代码设置,XML 里的
tintMode字段会被静默丢弃 - 如果用了
android:background而非android:src,tint和tintMode全部失效
tintMode 可选值对应哪些混合逻辑?别硬记,看效果反推
Android 支持的 tintMode 实际是 Porter-Duff 混合模式子集,不是 Photoshop 那套。最常踩坑的是把 multiply 当“变暗”,把 screen 当“变亮”,结果发现图标发灰或消失——因为混合对象是 tint 颜色和 vector 原图 alpha 通道,不是 RGB 像素叠加。
关键理解点:vector 图标本质是单色(alpha + 路径),tint 是上色源,tintMode 决定怎么把 tint “叠”到路径的透明度上。
-
tintMode="src_in":最常用,默认行为,tint 颜色只出现在原图不透明区域(安全、兼容性最好) -
tintMode="multiply":适合深色 tint + 浅色 icon,但若原图含半透区域,可能意外变暗甚至发黑 -
tintMode="screen":适合浅色 tint + 深色 icon,但容易过曝,尤其在白色背景上显得发虚 -
tintMode="add":API 29+ 才支持,慎用,部分低端机渲染异常
XML 中正确写法:属性位置和宿主控件有强绑定
不能把 tintMode 直接塞进 vector.xml 的根标签里期望全局生效。它必须由使用方控件驱动,且不同控件支持方式不同。
典型错误:vector.xml 里写 android:tintMode="src_in" —— 这个字段会被 aapt 忽略,毫无作用。
- 在
ImageView中:用android:tint+android:tintMode,仅 API 21+ 有效 - 在
AppCompatImageView中:用app:tint+app:tintMode,向下兼容到 API 14 - 不要在
vector.xml文件中写任何tint或tintMode相关属性 - 如果用
android:background显示 vector,所有 tint 行为都失效,改用android:src
运行时动态切换 tintMode 的兼容写法
想在点击时切 multiply → src_in?别只调 setImageTintMode(),漏掉 setColorFilter() 兼容旧版会出问题。
原因:API 21 以下 ImageView 不支持 tintMode,必须降级为 ColorFilter 手动模拟。
- 统一用
DrawableCompat.wrap(drawable)包装 vector drawable - 再调
DrawableCompat.setTintMode(wrapped, mode)和DrawableCompat.setTint(wrapped, color) - 最后
imageView.setImageDrawable(wrapped),避免直接用setImageTintList()(它不控制 mode) - 特别注意:
setTintMode()必须在setTint()之后调,否则某些 ROM 下 mode 不生效
最易被忽略的一点:vector 的 android:fillColor 如果设成非 #00000000(比如写了具体颜色),就会和 tint 叠加出不可控结果——务必确保原始 vector 中所有 fillColor 是透明或纯黑,把着色完全交给 tint 控制。

