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 中定义的颜色,避免硬编码颜色值。
  • 考虑可访问性 确保文本和背景之间有足够的对比度,特别是 onPrimaryonSurface 等颜色的选择。
  • 明暗主题支持 确保应用在明亮和暗黑主题下都能正常显示。
  • 使用语义化颜色 根据用途选择合适的颜色,例如错误信息使用 error 颜色。

在现代应用开发中,ColorScheme 的价值远超视觉装饰。它通过语义化的颜色命名和自动配对机制,为开发者提供了从单一种子颜色生成完整调色板的能力,支持明暗主题无缝切换,。每个颜色角色都有明确的使用场景,从主要的 primary 色调用于关键 UI 元素,到 surface 色彩定义卡片背景,再到 error 色彩处理错误状态,形成了一个完整而科学的颜色体系。

更重要的是,ColorScheme 自动处理了颜色的对比度控制,确保文本在任何背景上都具有足够的可读性,这对于构建无障碍应用至关重要。通过统一的颜色标准,所有 Material 组件都能自动适配当前主题,大大降低了开发复杂度,同时保证了整个应用视觉风格的一致性。


如果你有其他的看法,或者有什么想要的题目、或者想提供题目和答案,都欢迎在评论区留言。更多文章和视频知识资讯,大家可以关注我的公众号、掘金和 B 站 。

注册登录 后评论
    // 作者
    张风捷特烈 发布于 掘金
    • 0
    // 本帖子
    分类
    关键词
    // 相关帖子
    Coming soon...
    • 0
    Flutter 百题斩#14 | 说说你对 ColorScheme 的了解张风捷特烈 发布于 掘金