【Android UI】Android Tint 用法指南

Android 中 tint(着色)是一个非常强大的功能,它可以让你用一套图标资源适配多种颜色(例如夜间模式、点击变色、主题切换),而无需让 UI 切多套图。这里是Android 中 Tint 的全方位用法指南,涵盖了常用控件、特殊控件、代码实现以及进阶配置。

一、 常用控件的 Tint 用法

1. ImageView (图标着色)

最常用的场景,用于改变 src 图片的颜色。

  • XML:

    xml 复制代码
    <ImageView
        ...
        android:src="@drawable/ic_icon"
        app:tint="#FF0000" /> <!-- 推荐:兼容性更好 -->
    <!-- android:tint="#FF0000"  原生属性,但在某些版本可能有兼容问题 -->
  • 代码 (Kotlin):

    kotlin 复制代码
    imageView.setColorFilter(Color.RED) // 最简单
    // 或者使用 Compat 库 (推荐)
    ImageViewCompat.setImageTintList(imageView, ColorStateList.valueOf(Color.RED))
2. View / ViewGroup (背景着色)

用于改变 background 的颜色,比如让一个圆角矩形背景变色,而不改变形状。

  • XML:

    xml 复制代码
    <Button
        ...
        android:background="@drawable/bg_rounded_gray"
        app:backgroundTint="#00FF00" /> <!-- 推荐使用 app: 前缀 -->
  • 代码 (Kotlin):

    kotlin 复制代码
    ViewCompat.setBackgroundTintList(view, ColorStateList.valueOf(Color.BLUE))
3. TextView (复合图标着色)

用于改变 TextView 上下左右 (drawableLeft/drawableTop...) 图标的颜色。

  • XML (API 23+):

    xml 复制代码
    <TextView
        ...
        android:drawableTop="@drawable/ic_icon"
        android:drawableTint="#FF0000" />
  • 兼容方案 (API < 23):
    XML 中无法直接支持低版本,建议使用 DrawableCompat 在代码中处理,或者使用 app:drawableTint (依赖最新 AppCompat/Material 库)。


二、 特殊控件的 Tint 用法

Android 为很多特定组件提供了专属的 tint 属性:

控件 XML 属性 作用
CheckBox / RadioButton app:buttonTint 改变勾选框/圆圈的颜色
ProgressBar android:progressTint 改变进度条颜色 (API 21+)
ProgressBar (不确定) android:indeterminateTint 改变转圈圈加载动画的颜色
SeekBar android:thumbTint 改变拖动滑块的颜色
FloatingActionButton app:backgroundTint 改变悬浮按钮的底色
MaterialButton app:iconTint 改变按钮内部图标的颜色
BottomNavigationView app:itemIconTint 改变底部导航栏图标颜色 (通常配合 Selector)

三、 进阶:Tint Mode (混合模式)

除了设置颜色,你还可以设置 Tint Mode 来决定颜色如何与图片融合。

属性:app:tintMode (或 android:tintMode)。

常见的模式如下(假设图片是黑色的,Tint 是红色的):

  1. src_in (最常用)
    • 效果只保留图片形状,内容填充为 Tint 颜色。
    • 场景:将图标完全变色(如把黑色返回箭头变成红色)。
  2. src_atop
    • 效果:在图片不透明的地方绘制 Tint 颜色,透明的地方保持透明。如果图片本身有颜色(非纯黑),会覆盖在上面。
  3. multiply (正片叠底)
    • 效果:颜色相乘。使得图片变暗。
  4. screen (滤色)
    • 效果:让图片变亮。

四、 进阶:StateList (点击变色)

tint 不仅可以是一个颜色值,还可以是一个 ColorStateList(颜色选择器),实现点击时图标自动变色

1. 创建 res/color/selector_tint.xml:

xml 复制代码
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#FF0000" android:state_pressed="true" /> <!-- 按下变红 -->
    <item android:color="#000000" /> <!-- 默认黑色 -->
</selector>

2. 在 ImageView 中使用:

xml 复制代码
<ImageView
    ...
    android:clickable="true"
    android:src="@drawable/ic_icon"
    app:tint="@color/selector_tint" /> <!-- 引用上面的 selector -->

五、 代码动态设置 Tint (通用方案)

如果你拿到了一个 Drawable 对象(比如从网络下载的,或者通过代码生成的),想要给它着色,需要注意使用 mutate(),否则可能会影响到所有使用该资源的地方。

标准写法:

kotlin 复制代码
fun tintDrawable(drawable: Drawable, color: Int): Drawable {
    // 1. 包装 Drawable (使其兼容低版本)
    val wrappedDrawable = DrawableCompat.wrap(drawable).mutate()
    
    // 2. 设置颜色
    DrawableCompat.setTint(wrappedDrawable, color)
    
    // 如果需要设置 Mode
    // DrawableCompat.setTintMode(wrappedDrawable, PorterDuff.Mode.SRC_IN)
    
    return wrappedDrawable
}

使用示例:

kotlin 复制代码
val originalDrawable = ContextCompat.getDrawable(context, R.drawable.ic_icon)
imageView.setImageDrawable(tintDrawable(originalDrawable!!, Color.BLUE))

六、setColorFilter

简单来说,setColorFilter 就是给图片"加滤镜"。在 Android 开发中,它的核心作用是:**在不更换图片资源(PNG/JPG/Vector)的情况下,通过代码动态改变图片的显示颜色。**把它想象成给你的图片戴上了一副"有色眼镜"。

1. 核心用途
  • 复用图标:你只需要切一张黑色的图标,就能通过它变成白色、红色、蓝色等。这样可以减小 APK 体积。
  • 状态反馈:比如按钮被禁用时,用灰色滤镜让图片变暗;按钮按下时,加深颜色。
  • 主题适配:根据用户选择的主题(白天/黑夜),动态修改图标颜色。
2. 代码示例

通常在 ImageViewDrawable 上调用。

场景 A:把图标变成纯色 (最常用)

比如你有一个黑色的搜索图标,想让它变成红色。

java 复制代码
// Java
// PorterDuff.Mode.SRC_IN 是关键:它表示"取源图的形状,填入滤镜的颜色"
imageView.setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN); 
kotlin 复制代码
// Kotlin
imageView.setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN)

场景 B:清除滤镜 (恢复原样)

kotlin 复制代码
imageView.clearColorFilter()
3. 核心参数:PorterDuff.Mode (混合模式)

setColorFilter 的强大之处在于第二个参数 PorterDuff.Mode,它决定了颜色原图怎么混合。

最常用的几种模式:

  1. SRC_IN (重中之重)

    • 效果只保留图片的形状,完全填充成你设置的颜色。
    • 用途:给图标换色(比如把黑色箭头变成白色箭头)。
    • 这是 90% 的使用场景。
  2. MULTIPLY (正片叠底)

    • 效果:颜色相乘,画面变暗。
    • 用途:给背景图加一层遮罩,或者做"按下变暗"的效果。
  3. SRC_ATOP

    • 效果:在不透明的地方上色,透明的地方保持透明。如果原图本身有彩色,会覆盖在上面。

4. setColorFilter vs Tint

你刚才问的 tintsetColorFilter 其实是表兄弟关系:

  • tint (XML 属性) :这是声明式 写法。你在 XML 里写 app:tint,系统底层其实就是调用了 setColorFilter 相关的逻辑来渲染。
  • setColorFilter (Java/Kotlin 方法) :这是命令式写法。你在代码逻辑里手动控制。

区别在于:

  • tint 可以接受 ColorStateList(比如点击变色 selector)。
  • setColorFilter 通常一次只设置一种固定的颜色(虽然也可以自己写逻辑监听点击事件来切换)。

总结

  • 简单图标变色 :用 ImageViewapp:tint
  • 背景变色 :用 app:backgroundTint
  • 点击变色tint 属性引用 res/color/ 下的 selector 文件。
  • 特定控件 :找对应的 buttonTint, thumbTint, iconTint 等属性。
  • setColorFilter 就是代码版的"图标染色剂"。 当你需要在代码里把一个图标改成别的颜色,又不想去切新图时,就用它。
相关推荐
Android系统攻城狮5 小时前
Android16之交叉编译系统压力测试利器:stress-ng(二百六十六)
android·压力测试·android16·系统调试
杨忆5 小时前
导航栏左右拖动切换
android
shuaijie05185 小时前
在Vue.js中实现列表的拖动功能,使用第三方库如vuedraggable(基于Sortable.js)
android·javascript·vue.js
毕设源码-郭学长5 小时前
【开题答辩全过程】以 基于Android的儿童托管系统为例,包含答辩的问题和答案
android
sky丶Mamba5 小时前
CentOS Stream 9安装MySQL
android·mysql·centos
wei115565 小时前
framework.jar使用
android
Lei活在当下14 小时前
【项目踩坑实录】并发环境下,Glide缓存引起的图片加载异常
android·debug·glide
my_power52016 小时前
检出git项目到android studio该如何配置
android·git·android studio
三少爷的鞋19 小时前
Repository 方法设计:suspend 与 Flow 的决选择指南(以朋友圈为例)
android