Flutter 百题斩#14 | 说说你对 ColorScheme 的了解
最近在着手开发我的 《匠心星问》 ,它定位是一款 题库 应用,将集题目浏览、发布、解答、做题为一体。打算第一步先以 Flutter 为核心,准备题库资源。于是诞生《每日一题》 系列,准备精心设计一些 Flutter 的问题与解答,作为题库的养料。本文的焦点是探讨:
说说你对 ColorScheme 的了解
ColorScheme 是 Flutter Material Design 3 的颜色系统核心,它定义了应用程序的完整颜色主题。作为一套包含 46 种颜色角色的系统化方案,ColorScheme 不仅确保了应用在不同组件间的视觉一致性,更承载着品牌识别、用户体验优化和可访问性保障的重要使命。
- | - |
---|---|
|
|
一、 什么是 ColorScheme?
简单来说,ColorScheme 是 Flutter 中以主题色为基准,提供的 45 种颜色构成的颜色合集。通过 ColorScheme.fromSeed 构造函数,可以基于一个种子颜色,自动计算出这 45 种颜色:
ColorScheme.fromSeed(seedColor: Colors.deepPurple)
- 比如默认的
Colors.deepPurple
对应的如下 45 种颜色 :
Colors.orange
对应颜色如下:
Colors.lightGreen
对应颜色如下:
二、ColorScheme 颜色体系总览
46 种颜色听起来很多,但是主要分为五个类别:
- 🔵 Primary 组: FAB、重要按钮、激活状态
- 🟠 Secondary 组: 筛选 Chip 、次要操作
- 🟢 Tertiary 组: 输入框、对比强调元素
- 🔴 Error 组: 错误提示、警告状态
- ⬜ Surface 组: 卡片、对话框、背景层次
┌─────────────────────────────────────────────────────────────┐
│ 🔵 Primary (8) ████████████████████ 17.8% │
│ 🟠 Secondary (8) ████████████████████ 17.8% │
│ 🟢 Tertiary (8) ████████████████████ 17.8% │
│ 🔴 Error (4) ██████████ 8.9% │
│ ⬜ Surface (14) ███████████████████████████████ 31.1% │
│ ⚠️ Deprecated (3) ██████ 6.7% │
└─────────────────────────────────────────────────────────────┘
1. 主要颜色组 (Primary)
核心作用: 品牌主色系,承载应用最重要的视觉识别和关键交互元素。Primary 颜色组是整个应用的视觉灵魂,它直接体现品牌特色并引导用户的核心操作流程。
🔵 主要颜色组 (Primary)
├── 🟦 primary - 主色调,关键UI元素
├── ⬜ onPrimary - 主色调上的文本/图标
├── 🟪 primaryContainer - 主色容器背景
├── ⬛ onPrimaryContainer - 主色容器上的文本
├── 🔷 primaryFixed - 固定主色(明暗主题不变)
├── 🔹 primaryFixedDim - 固定主色(较暗)
├── ⚪ onPrimaryFixed - 固定主色上的文本
└── ⚫ onPrimaryFixedVariant - 固定主色上的低强调文本
2. 次要颜色组 (Secondary)
核心作用: 辅助主色的次要色系,用于中等重要度的UI元素,提供视觉层次感。Secondary 颜色组扮演着"绿叶"的角色,它既不会抢夺主色的风头,又能有效地组织信息层次。
🟠 次要颜色组 (Secondary)
├── 🟧 secondary - 次要色调,辅助强调
├── ⬜ onSecondary - 次要色调上的文本/图标
├── 🟫 secondaryContainer - 次要色容器背景
├── ⬛ onSecondaryContainer - 次要色容器上的文本
├── 🔶 secondaryFixed - 固定次要色
├── 🔸 secondaryFixedDim - 固定次要色(较暗)
├── ⚪ onSecondaryFixed - 固定次要色上的文本
└── ⚫ onSecondaryFixedVariant - 固定次要色上的低强调文本
3. 第三颜色组 (Tertiary)
核心作用: 第三级色彩系统,用于创造视觉对比和强调,丰富界面色彩层次。Tertiary 颜色组是色彩系统中的"调味剂",它为界面增添活力和个性,避免单调的双色设计。
🟢 第三颜色组 (Tertiary)
├── 🟩 tertiary - 第三级色调,平衡对比
├── ⬜ onTertiary - 第三级色调上的文本/图标
├── 🟤 tertiaryContainer - 第三级色容器背景
├── ⬛ onTertiaryContainer - 第三级色容器上的文本
├── 💚 tertiaryFixed - 固定第三级色
├── 🌿 tertiaryFixedDim - 固定第三级色(较暗)
├── ⚪ onTertiaryFixed - 固定第三级色上的文本
└── ⚫ onTertiaryFixedVariant - 固定第三级色上的低强调文本
4. 表面颜色组 (Surface)
核心作用: 最庞大的背景色系统,定义应用的空间层次结构和深度感。Surface 颜色组是 Material 3 设计系统的重大革新,它用细腻的层次变化替代了传统的阴影系统。这套系统让开发者能够精确控制UI的视觉层次,创造出既现代又易用的界面体验。
⬜ 表面颜色组 (Surface)
├── ⬜ surface - 基础表面背景
├── ⬛ onSurface - 表面上的文本
├── 🌫️ surfaceDim - 较暗表面
├── ☀️ surfaceBright - 较亮表面
├── 📄 surfaceContainerLowest - 最低层容器
├── 📋 surfaceContainerLow - 低层容器
├── 📦 surfaceContainer - 标准容器
├── 📊 surfaceContainerHigh - 高层容器
├── 📈 surfaceContainerHighest - 最高层容器
├── 🔘 onSurfaceVariant - 表面变体上的文本
├── ➖ outline - 边框线条
├── ⚬ outlineVariant - 边框变体
├── 🌑 shadow - 阴影颜色
├── 🎭 scrim - 遮罩颜色
├── 🔄 inverseSurface - 反转表面
├── 🔄 onInverseSurface - 反转表面上的文本
├── 🔄 inversePrimary - 反转主色
└── 🎨 surfaceTint - 表面着色
5. 错误颜色组 (Error)
核心作用: 专门的错误状态色系,确保所有错误相关UI反馈的一致性表达。Error 颜色组虽然只有4种颜色,但承担着关键的用户体验职责。它确保所有错误状态都有统一、清晰的视觉反馈。
🔴 错误颜色组 (Error)
├── 🔴 error - 错误状态颜色
├── ⬜ onError - 错误色上的文本/图标
├── 🟥 errorContainer - 错误容器背景
└── ⬛ onErrorContainer - 错误容器上的文本
Material 3 中部分颜色已被新的 Surface 系统替代
⚠️ 已弃用颜色 (向后兼容保留)
├── 🗑️ background → 使用 surface 替代
├── 🗑️ onBackground → 使用 onSurface 替代
└── 🗑️ surfaceVariant → 使用 surfaceContainerHighest 替代
三、创建 ColorScheme 对象与使用
ColorScheme 的值会直接影响绝大多数 Material 风格组件的表现效果,比如各种按钮、Slider、Switch、TextFiled 等。如下所示是三种色系下组件的颜色表现效果:
1. 使用 ColorScheme
可以通过 ColorScheme.fromSeed 构造,根据一个种子颜色,生成对象。你可以在 MaterialApp
组件或 Theme
组件中,在 ThemeData 数据的创建中使用它:
final ColorScheme scheme = ColorScheme.fromSeed(seedColor: Colors.blue);
MaterialApp(
theme: ThemeData(
colorScheme: scheme,
),
...
Theme(
data: ThemeData(
colorScheme: scheme,
...
2. 在组件中访问颜色
ColorScheme.fromSeed 是 Flutter 框架根据一个颜色自动计算得到的 46 种颜色,可能某些色彩并不符合你的预期。此时,你也可以主动创建 ColorScheme 对象,让设计师提供配色方案。ColorScheme 的价值在于让你拥有了 46 种颜色的定义权,这些颜色可以通过上下文在任何地方被共享。
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
color: colorScheme.surface,
child: Text(
'Hello Flutter',
style: TextStyle(color: colorScheme.onSurface),
),
);
}
}
3. ColorScheme 暗色和亮色模式
ColorScheme 的色彩空间是支持暗色模式的,通过 brightness
参数指定暗亮模式:其中各种颜色会根据种子颜色和暗亮模式自动计算得到。
ColorScheme scheme = ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: Brightness.dark,
);
ColorScheme 名称中带 Fixed 的颜色,不会随暗色和亮色模式而改变。三组 12 个 Fixed 的颜色,对应在切换暗亮模式时颜色不希望改变的组件,很有用。
4. Surface 容器层层次结构
Surface 颜色系统是 Material 3 设计语言的核心创新,它彻底改变了传统的阴影层次表达方式。通过精心设计的色调变化,Surface 系统创造出更加自然、现代的空间深度感知。提供了科学的层次分级:
- 海拔高度: Lowest → Low → Standard → High → Highest
- 透明度替代: 基于色调的科学分层,替代旧的透明度叠加
- 动态适应: 自动适配明暗主题,保持视觉一致性
┌─────────────────────────────────────────────────────────────┐
│ 🎨 surfaceTint │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 📈 surfaceContainerHighest │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ 📊 surfaceContainerHigh │ │ │
│ │ │ ┌─────────────────────────────────────┐ │ │ │
│ │ │ │ 📦 surfaceContainer │ │ │ │
│ │ │ │ ┌─────────────────────────────┐ │ │ │ │
│ │ │ │ │ 📋 surfaceContainerLow │ │ │ │ │
│ │ │ │ │ ┌─────────────────────┐ │ │ │ │ │
│ │ │ │ │ │ 📄 surfaceContainer │ │ │ │ │ │
│ │ │ │ │ │ Lowest │ │ │ │ │ │
│ │ │ │ │ │ ┌─────────────┐ │ │ │ │ │ │
│ │ │ │ │ │ │ ⬜ surface │ │ │ │ │ │ │
│ │ │ │ │ │ └─────────────┘ │ │ │ │ │ │
│ │ │ │ │ └─────────────────────┘ │ │ │ │ │
│ │ │ │ └─────────────────────────────┘ │ │ │ │
│ │ │ └─────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
四、总结
ColorScheme 的其价值在于:
- 保持一致性 始终使用 ColorScheme 中定义的颜色,避免硬编码颜色值。
- 考虑可访问性 确保文本和背景之间有足够的对比度,特别是
onPrimary
、onSurface
等颜色的选择。 - 明暗主题支持 确保应用在明亮和暗黑主题下都能正常显示。
- 使用语义化颜色 根据用途选择合适的颜色,例如错误信息使用
error
颜色。
在现代应用开发中,ColorScheme 的价值远超视觉装饰。它通过语义化的颜色命名和自动配对机制,为开发者提供了从单一种子颜色生成完整调色板的能力,支持明暗主题无缝切换,。每个颜色角色都有明确的使用场景,从主要的 primary 色调用于关键 UI 元素,到 surface 色彩定义卡片背景,再到 error 色彩处理错误状态,形成了一个完整而科学的颜色体系。
更重要的是,ColorScheme 自动处理了颜色的对比度控制,确保文本在任何背景上都具有足够的可读性,这对于构建无障碍应用至关重要。通过统一的颜色标准,所有 Material 组件都能自动适配当前主题,大大降低了开发复杂度,同时保证了整个应用视觉风格的一致性。
如果你有其他的看法,或者有什么想要的题目、或者想提供题目和答案,都欢迎在评论区留言。更多文章和视频知识资讯,大家可以关注我的公众号、掘金和 B 站 。