【Android UI】Android 颜色的表示和获取使用指南

在 Android 开发中,颜色的表示和获取方式非常多样,涵盖了从底层十六进制代码到高层主题属性引用的各个层面,以下是 Android 中关于颜色表示的完整指南。

1. 十六进制颜色值 (Hex Color Codes)

这是 Android 中颜色的底层表达方式。颜色由 Alpha (透明度)Red (红)Green (绿)Blue (蓝) 通道组成。

格式: #AARRGGBB (最常用) 或 #RRGGBB (默认不透明)。

组成:

  • AA: 透明度 (00=全透明, FF=不透明)。
  • RR: 红色值。
  • GG: 绿色值。
  • BB: 蓝色值。

示例:

  • #FF000000 (不透明黑色)
  • #80FF0000 (半透明红色 - 50%透明度)
  • #FFFFFF (白色,隐含 FF 透明度)

透明度参照表:

00%=FF(不透明)

5%=F2

10%=E5

15%=D8

20%=CC

25%=BF

30%=B2

35%=A5

40%=99

45%=8c

50%=7F

55%=72

60%=66

65%=59

70%=4c

75%=3F

80%=33

85%=21

90%=19

95%=0c

100%=00(全透明)

2. 在 XML 资源中定义颜色 (Color Definition)

为了方便管理和复用,通常会在 res/values/colors.xml 文件中定义颜色。

文件路径: res/values/colors.xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 定义一个不透明颜色 -->
    <color name="colorPrimary">#6200EE</color>
    
    <!-- 定义带透明度的颜色 -->
    <color name="black_overlay">#66000000</color>
    
    <!-- 引用其他颜色 -->
    <color name="theme_default">@color/colorPrimary</color>

	<!-- 引用 Android 中颜色:transparent是透明色  -->
	<color name="transparent_default">@android:color/transparent</color>
	<color name="white_default">@android:color/white</color>

</resources>

3. 在 XML 布局中使用颜色

在布局文件(如 activity_main.xml)或样式文件(styles.xml)中引用颜色。

A. 引用资源颜色 (推荐)

这是最标准的做法,支持日夜间模式切换。

xml 复制代码
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="@color/colorPrimary" />
B. 直接使用 Hex 值 (硬编码,不推荐)

仅用于临时测试,不建议在正式代码中使用。

xml 复制代码
<View
    android:background="#FF0000" ... />
C. 引用主题属性 (Attribute References)

这是 Material Design 和现代 Android 开发的核心。你不直接引用具体颜色,而是引用"当前主题下的某个语义颜色"。这是实现深色模式 (Dark Mode) 的关键。

语法: ?attr/属性名?android:attr/属性名

xml 复制代码
<TextView
    <!-- 使用当前主题定义的 "colorPrimary" 颜色 -->
    android:textColor="?attr/colorPrimary"
    <!-- 使用当前主题定义的背景色 -->
    android:background="?android:attr/colorBackground" />
  • ?android:attr/... :引用的是 Android 操作系统原生 的属性。
  • ?attr/... :引用的是 App 项目自身或第三方库(如 AppCompat / Material Design 库) 定义的属性。
特性 ?android:attr/colorControlNormal ?attr/colorControlNormal
全称 Android System Attribute Application/Library Attribute
定义位置 Android SDK 源代码中 (framework) AppCompat / Material 库中 (values/attrs.xml)
引入版本 API 21 (Android 5.0) AppCompat 库引入时(支持旧版本)
兼容性 。如果在 API 21 以下的手机运行,会崩溃或找不到资源。 。AppCompat 库通过"垫片"机制,让它在低版本(如 API 19)上也能工作。
命名空间 显式指定 android: 命名空间 隐式使用当前 App (通常是 res-auto)

对于颜色、样式属性(尤其是 Material Design 相关的):
永远优先去掉 android: 前缀 。用 ?attr/colorPrimary?attr/colorControlNormal。让 AndroidX 库帮你处理兼容性问题。

对于系统底层通用属性(很老的属性):

如果 IDE 提示找不到不带前缀的属性,或者你知道这是一个非常基础的属性(如 ?android:attr/selectableItemBackground?android:attr/listDivider),则使用 android: 前缀。

简单记忆:

只要是关于 主题色 (Primary/Secondary)控件着色 (Control) 的,统统不要android:

4. 颜色状态列表 (Color State List / Selector)

ColorStateList 是 Android 中一个非常重要的概念,它本质上不是一个单一的颜色,而是一组颜色的集合。它根据 View 的当前状态(按下、聚焦、禁用、选中等)返回不同的颜色值。

A. 什么是 ColorStateList

通常在 XML 中定义(即 <selector>),用于 View 在不同状态(按下、选中、禁用等)下显示不同颜色的情况。

文件路径: res/color/button_text_color.xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 按下状态显示红色 -->
    <item android:color="#FF0000" android:state_pressed="true"/>
    
    <!-- 禁用状态显示灰色 -->
    <item android:color="#808080" android:state_enabled="false"/>
    
    <!-- 默认状态显示黑色 -->
    <item android:color="#000000"/>
</selector>

使用方式:

像普通颜色一样引用它:

xml 复制代码
<Button
    android:textColor="@color/button_text_color" ... />
B. Color (int) 转 ColorStateList

当你有一个单一的颜色值(int),但某个 API(如 TextView.setTextColor(ColorStateList))需要 ColorStateList 参数时,可以使用以下方式转换。这也意味着无论 View 处于什么状态,都显示同一个颜色。

Java / Kotlin:

java 复制代码
int myColor = Color.RED;
// int myColor = context.getColor(R.color.my_color)

// 转换方法
ColorStateList csl = ColorStateList.valueOf(myColor);

// 使用
textView.setTextColor(csl);
C. ColorStateList 转 Color (int)

注意: 不能直接把 ColorStateList 变成一个通用的颜色,因为必须指定"状态"才能知道取哪个颜色。

通常我们需要获取当前状态下的颜色

java 复制代码
ColorStateList csl = ContextCompat.getColorStateList(context, R.color.my_selector);

// 获取 View 的当前状态数组 (例如一个 Button)
int[] state = button.getDrawableState(); 

// 参数2:如果找不到匹配状态,返回的默认颜色
int colorForCurrentState = csl.getColorForState(state, Color.BLACK); 

// 或者手动指定获取 "按下" 状态的颜色
int colorPressed = csl.getColorForState(new int[]{android.R.attr.state_pressed}, Color.BLACK);
D. 在代码中动态创建 ColorStateList (复杂,不常用)

如果不想用 XML,可以用代码构造,但比较繁琐:

java 复制代码
int[][] states = new int[][] {
    new int[] { android.R.attr.state_enabled }, // enabled
    new int[] { -android.R.attr.state_enabled }, // disabled
    new int[] {} // default
};

int[] colors = new int[] {
    Color.BLACK,
    Color.GRAY,
    Color.BLACK
};

ColorStateList csl = new ColorStateList(states, colors);

5. 在 Java/Kotlin 代码中获取颜色

在代码中,颜色通常以 int 类型表示(不要混淆 Resource IDColor Int)。

A. 获取资源中的颜色 (标准方式)

使用 ContextCompat (推荐,兼容性最好):

java 复制代码
// Java/Kotlin
int color = ContextCompat.getColor(context, R.color.colorPrimary);

原生方式 (Android M/API 23+):

kotlin 复制代码
val color = context.getColor(R.color.colorPrimary)

过时方式 (Deprecated, 尽量避免):

java 复制代码
// 在旧版本中常用,现在已弃用,因为它无法正确处理主题
int color = getResources().getColor(R.color.colorPrimary); 
B. 解析 Hex 字符串

如果你从服务器获取了一个颜色代码字符串(如 "#FF0000"):

java 复制代码
// Java/Kotlin
import android.graphics.Color;

try {
    int color = Color.parseColor("#FF0000");
    view.setBackgroundColor(color);
} catch (IllegalArgumentException e) {
    // 处理格式错误
}
C. 使用 Color 类常量

Android Color 类提供了一些预定义的静态常量:

java 复制代码
view.setBackgroundColor(Color.RED);
// 透明色
view.setBackgroundColor(Color.TRANSPARENT);
D. 动态构建颜色 (ARGB)

如果你需要动态计算颜色(例如根据滑动进度改变透明度):

java 复制代码
// Java: Color.argb(alpha, red, green, blue) - 范围 0-255
int customColor = Color.argb(255, 100, 200, 50);

// Kotlin 扩展 (Android KTX)
val color = Color.valueOf(1.0f, 0.5f, 0.3f) // 范围 0.0-1.0 (API 26+)
E. 获取主题属性颜色 (Theme Attribute)

在代码中获取 ?attr/colorPrimary 这种动态颜色比较麻烦,需要解析主题:

java 复制代码
// java
public static int getThemeColor(Context context, int attrId) {
    TypedValue typedValue = new TypedValue();
    Theme theme = context.getTheme();
    // resolveAttribute 返回 true 表示找到了该属性
    if (theme.resolveAttribute(attrId, typedValue, true)) {
        return typedValue.data;
    }
    // 如果找不到,返回一个默认颜色(例如红色报错)
    return Color.RED; 
}

// 使用
// 获取 textColorPrimary (Android 系统自带属性)
int textPrimary = getThemeColor(this, android.R.attr.textColorPrimary);
// 设置给 View
textView.setTextColor(textPrimary );
kotlin 复制代码
// Kotlin 扩展函数示例
fun Context.getThemeColor(attrId: Int): Int {
    val typedValue = TypedValue()
    theme.resolveAttribute(attrId, typedValue, true)
    return typedValue.data
}

// 使用
val primaryColor = context.getThemeColor(com.google.android.material.R.attr.colorPrimary)

SettingsLib 中有工具类获取主题颜色值,可以参考:

java 复制代码
//SettingsLib/src/com/android/settingslib/Utils.java

@ColorInt
public static int getColorAttrDefaultColor(Context context, int attr) {
    TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
    @ColorInt int colorAccent = ta.getColor(0, 0);
    ta.recycle();
    return colorAccent;
}

public static ColorStateList getColorAttr(Context context, int attr) {
    TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
    ColorStateList stateList = null;
    try {
        stateList = ta.getColorStateList(0);
    } finally {
        ta.recycle();
    }
    return stateList;
}

6. 颜色类型对照表

方式 语法/代码示例 适用场景
Hex 码 #FF0000, #80FFFFFF 这里定义,UI设计稿对照
XML 定义 <color name="red">#FF0000</color> colors.xml 统一管理
XML 引用 @color/red 布局文件常规使用
主题引用 ?attr/colorPrimary 推荐,支持深色模式和换肤
状态列表 res/color/selector.xml 按钮点击、文字禁用态
代码获取 ContextCompat.getColor(...) 逻辑中需要设置颜色
代码解析 Color.parseColor("#...") 处理服务端下发颜色

7. 主题中常用的属性颜色值和含义

styles.xmlthemes.xml 中,以及布局引用(?attr/...)时,以下是最常用的语义化颜色属性。

A. 品牌/结构颜色 (Material Design)
属性名 (attr) 含义 典型用途
colorPrimary 主色调 App 的品牌色,用于 Toolbar、按钮背景等。
colorSecondary 次色调 强调色,用于 FAB 按钮、Switch 开关激活态、进度条等。
colorBackground 窗口背景色 Activity 的默认底色(浅色模式白,深色模式黑)。
colorSurface 表面色 CardView、BottomSheet、菜单的背景色。
B. 文本颜色 (Framework)
属性名 (android:attr) 含义 典型用途
textColorPrimary 主要文本色 标题、正文,最醒目的文字(深色模式下自动变浅)。
textColorSecondary 次要文本色 副标题、描述性文字,透明度较低。
textColorHint 提示文本色 EditText 的 hint 颜色。
C. 控件交互颜色 (Control)

这是自定义控件时最需要关注的系统属性:

属性名 (attr) 含义 典型用途
colorControlNormal 默认状态色 图标默认颜色、CheckBox 未选中时的边框色、EditText 未聚焦时的下划线。
colorControlActivated 激活状态色 CheckBox 选中时的颜色、EditText 聚焦时的下划线/光标(通常等于 colorSecondary 或 colorPrimary)。
colorControlHighlight 高亮/波纹色 按钮点击时的水波纹效果 (Ripple) 颜色。

8. ContextCompat 和 Context 的区别

  • Context : 是 Android 系统核心抽象类(环境上下文)。随着 Android 版本升级(API 21, 23, 26...),Context 类的方法签名和行为发生了变化。直接使用 Context 的某些方法可能会导致在旧手机上崩溃。
  • ContextCompat : 是 AndroidX (以前的 Support Library) 提供的一个帮助类(Helper Class)。它的作用是屏蔽系统版本的差异,提供统一的 API 接口。
A. 为什么要有 ContextCompat?

以获取颜色为例:

Android 6.0 (API 23) 之前: context.getResources().getColor(R.color.red)

Android 6.0 (API 23) 及之后: Google 废弃了上面的方法,引入了 context.getColor(R.color.red)(为了更好地支持主题化)。

如果你直接写代码:

java 复制代码
// 如果你在 API 21 的手机上运行这段代码(调用了 API 23 才有的方法),APP 会直接 Crash
context.getColor(R.color.red); 

如果你使用 ContextCompat:

java 复制代码
// ContextCompat 内部会自动判断当前手机系统版本
// if (SDK >= 23) call context.getColor()
// else call resources.getColor()
ContextCompat.getColor(context, R.color.red);
B. 使用场景总结

凡是涉及到获取资源(颜色、图片)或者系统权限 相关的操作,闭着眼睛使用 ContextCompat,它是最稳妥的方案。

场景 推荐使用 原因
获取资源 (Color, Drawable) ContextCompat 强烈推荐。防止 API 版本兼容性崩溃,且解决旧方法 Deprecated 警告。
检查权限 ContextCompat checkSelfPermission 在旧版本处理方式不同,兼容库帮你处理了。
启动 Activity/Service Context 核心功能,直接用 Context 即可。
获取系统服务 ContextCompat ContextCompat.getSystemService 某些情况下更安全,但通常直接用 Context 也没问题。
相关推荐
阿巴斯甜6 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker7 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95278 小时前
Andorid Google 登录接入文档
android
黄林晴9 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android