TintList 使用技术文档

本文档详细介绍 Android 开发中 TintList 的概念、作用以及使用方法,帮助开发者掌握如何利用 TintList 动态改变控件的颜色。


1. 概述

在 Android 应用开发中,经常需要对控件的背景、图标等元素进行着色处理,以便实现动态主题、状态变化反馈或与应用整体风格保持一致。ColorStateList 是 Android 中一种描述颜色状态的对象,而 TintList 则通常指控件的背景或图标的“着色列表”,其底层实现就是使用 ColorStateList 对控件进行着色处理。

例如,许多控件(如 Button、ImageView、FloatingActionButton 等)提供了 setBackgroundTintList()setImageTintList() 等方法,使得开发者可以轻松地为控件设置不同状态下的颜色。


2. ColorStateList 基础

具体可看我的另一篇文章ColorStateList使用详解 | GoshenC

2.1 什么是 ColorStateList

ColorStateList 是一个表示颜色列表的数据结构,能够根据控件当前的状态(如按下、聚焦、禁用等)返回不同的颜色。
例如,可以定义如下 XML 文件:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 按下状态 -->
<item android:state_pressed="true" android:color="#FF0000" />
<!-- 默认状态 -->
<item android:color="#00FF00" />
</selector>

当控件处于按下状态时,其颜色会变为红色,否则为绿色。

2.2 动态创建 ColorStateList

除了在 XML 中定义,开发者也可以在代码中动态创建 ColorStateList,例如:

1
2
3
4
5
6
val colors = intArrayOf(Color.RED, Color.GREEN)
val states = arrayOf(
intArrayOf(android.R.attr.state_pressed), // 按下状态
intArrayOf() // 默认状态
)
val colorStateList = ColorStateList(states, colors)

3. TintList 的使用

在大多数场景中,“tintList” 通常指控件的 tint 属性,即背景或图标的着色列表。以下以背景 TintList 为例说明其使用方法。

3.1 控件背景着色

许多控件都支持背景 tint 设置,这样可以将控件的背景颜色通过 ColorStateList 进行动态控制。例如,设置 FloatingActionButton 的背景 tint:

1
2
3
4
5
6
7
// 引入必要的包
import android.content.res.ColorStateList
import android.graphics.Color
import com.google.android.material.floatingactionbutton.FloatingActionButton

// 假设 fab 为 FloatingActionButton 实例
fab.backgroundTintList = ColorStateList.valueOf(Color.WHITE)

上例中,ColorStateList.valueOf(Color.WHITE) 创建了一个只有白色的颜色状态列表,强制将控件背景显示为白色。

3.2 图标着色

类似地,ImageView 和其他支持 tint 的控件也可以使用 setImageTintList() 方法:

1
2
// 假设 imageView 为 ImageView 实例
imageView.imageTintList = ColorStateList.valueOf(Color.BLUE)

这样,ImageView 中的图片将会应用蓝色着色。


4. 使用案例:自定义 Snackbar 背景和文字颜色

以 Snackbar 为例说明如何使用 TintList 修改其背景颜色。默认情况下,Snackbar 的背景和文字颜色由 Material Design 主题控制,但有时需要自定义显示效果。

4.1 示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
binding.fab.setOnClickListener { view ->
// 创建 Snackbar 对象
val snackbar = Snackbar.make(view, "Data deleted", Snackbar.LENGTH_SHORT)
.setAction("Undo") {
Toast.makeText(this, "Data restored", Toast.LENGTH_SHORT).show()
}

// 获取 Snackbar 的根布局
val snackbarView = snackbar.view

// 使用 TintList 强制设置背景为白色
snackbarView.backgroundTintList = ColorStateList.valueOf(Color.WHITE)

// 修改消息文本颜色为黑色
val textView = snackbarView.findViewById<TextView>(com.google.android.material.R.id.snackbar_text)
textView?.setTextColor(Color.BLACK)

// 修改 Action 按钮文本颜色(例如蓝色)
val actionTextView = snackbarView.findViewById<TextView>(com.google.android.material.R.id.snackbar_action)
actionTextView?.setTextColor(Color.BLUE)

// 显示 Snackbar
snackbar.show()
}

4.2 代码讲解

  • 创建 Snackbar:
    Snackbar.make(view, "Data deleted", Snackbar.LENGTH_SHORT) 创建一个 Snackbar,其提示文本为 “Data deleted”,持续时间为短暂显示,并通过 setAction("Undo") 为其添加一个操作按钮。当点击 “Undo” 按钮时,将弹出 Toast。
  • 获取根布局:
    snackbar.view 返回 Snackbar 的根布局(通常为 Snackbar.SnackbarLayout),这使得我们可以修改其背景和内部控件的属性。
  • 设置背景 TintList:
    snackbarView.backgroundTintList = ColorStateList.valueOf(Color.WHITE) 使用 ColorStateList 将背景颜色强制着色为白色。
    这里的 ColorStateList.valueOf(Color.WHITE) 生成了一个只包含单一颜色的状态列表,无论控件处于何种状态都显示白色。
  • 修改文本颜色:
    通过 findViewById 方法分别获取用于显示主要消息和 Action 按钮文本的 TextView,并将它们的文本颜色分别设置为黑色和蓝色。
  • 显示 Snackbar:
    调用 snackbar.show() 显示 Snackbar。

5. TintList 的应用场景

  • 动态主题切换: 根据用户选择的主题动态改变控件颜色。
  • 状态反馈: 根据控件状态(如按下、禁用等)显示不同颜色反馈。
  • 自定义控件: 对于自定义控件,可以通过 TintList 实现颜色的动态更新,而无需创建多个不同的资源文件。

6. 注意事项

  • 主题覆盖: 在某些情况下,应用主题可能会覆盖代码中对 TintList 的设置。如果出现这种情况,请检查应用的主题配置或通过样式文件自定义相关控件的默认行为。
  • 兼容性: 大多数支持 tint 的控件都可以使用 TintList,但对某些自定义控件需要确保它们正确实现了 tint 属性。
  • 资源缓存: 修改后可能需要清理缓存或重启 IDE 才能看到效果。

7. 总结

TintList(通过 ColorStateList 实现)是 Android 应用开发中一个强大的工具,能够帮助开发者根据控件状态动态修改颜色。无论是背景、图标还是文本颜色,通过正确使用 TintList,都可以使应用 UI 更加灵活和响应用户需求。希望本技术文档能帮助你更好地理解并应用 TintList 技术。

我的实际应用

这是我在修改snackbar中使用到的TinitList,因为默认snackbar的是黑底白字,我想改成白底黑字,在修改snackbar的背景颜色发现居然一定得使用TintList,否则修改不了,于是我有感而发,写下这篇文章。以下是我当时代码中关于TinitList的部分,希望能帮助你理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
binding.fab.setOnClickListener { view ->
val snackbar = Snackbar.make(view, "Data deleted", Snackbar.LENGTH_SHORT)
.setAction("Undo") {
Toast.makeText(this, "Data restored", Toast.LENGTH_SHORT).show()
}

//获取 Snackbar 的 View 并设置 tintList 强制背景为白色.tiniList超级超级超级级厉害的,能强制修改颜色,
//可用在button,ImageView,FloatingActionButton,但不能用在popupmenu上,修改popupmenu需要在value中定义style,然后在layout中使用这个style
val snackbarView = snackbar.view
snackbarView.backgroundTintList = ColorStateList.valueOf(Color.WHITE)

// 设置文字为黑色
val textView = snackbarView.findViewById<TextView>(com.google.android.material.R.id.snackbar_text)
textView?.setTextColor(Color.BLACK)

// 设置 Action 按钮的颜色(这里示例用黑色,你可以换成其它颜色)
val actionTextView = snackbarView.findViewById<TextView>(com.google.android.material.R.id.snackbar_action)
actionTextView?.setTextColor(Color.BLUE)

snackbar.show()
}