第2章:ColorScheme 深度配置
Material3 的配色系统以 ColorScheme 为核心,通过定义 Primary、Secondary、Tertiary 三大色值,并借助 Harmonized Colors 机制,将品牌色自动映射到语义角色(如 Surface、OnBackground 等)。本章从原理出发,逐步讲解如何自定义色值、启用调和、验证结果,并规避常见陷阱。
2.1 核心原理
ColorScheme 共包含 12 个语义色槽,其中 Primary、Secondary、Tertiary 是品牌色源。Harmonized Colors 是一套色彩调和算法,它通过色轮旋转、明度缩放等手段,确保同组色值满足无障碍对比度(WCAG AA),同时保留品牌视觉特征。系统自动生成 5 个色调(0‑200)以覆盖不同状态(如 Hover、Press)。
| 色槽 | 来源 | Harmonized 后影响 |
|---|---|---|
primary | 品牌主色 | 控制 topAppBar、FAB、按钮 |
secondary | 品牌辅助色 | 控制 chip、switch、进度指示器 |
tertiary | 品牌第三色 | 控制输入框焦点、badge |
surface/background | 自动派生 | 基于 primary 调和的极浅色 |
onPrimary 等 | 自动派生 | 保证对比度≥4.5:1 |
2.2 实现流程
- 提取品牌色值(HEX 或 RGB)。
- 在 Material3 主题构造时,使用
ColorScheme.fromSeed或手动构造ColorScheme。 - (可选)对特定色值调用
Color.harmonizeWith进行调和。 - 将自定义
ColorScheme注入MaterialApp.theme。 - 在 UI 层使用
Theme.of(context).colorScheme引用。
提示:强烈建议使用 fromSeed 而非手动填入每一个色槽,因为后者容易破坏调和关系且无法自动适配深色模式。
2.3 代码配置示范
以下 Flutter 代码展示了如何自定义三原色,并启用 Harmonized Colors:
// 品牌色定义(在 constants.dart 中)
class BrandColors {
static const Color primary = Color(0xFF1565C0); // 深蓝
static const Color secondary = Color(0xFF43A047); // 绿
static const Color tertiary = Color(0xFFEF6C00); // 橙
}
// 主题构造(app_theme.dart)
final ColorScheme customScheme = ColorScheme.fromSeed(
seedColor: BrandColors.primary,
secondary: BrandColors.secondary,
tertiary: BrandColors.tertiary,
brightness: Brightness.light,
// 以下两行手动启用调和(fromSeed 默认已开启)
primary: BrandColors.primary.harmonizeWith(BrandColors.primary),
secondary: BrandColors.secondary.harmonizeWith(BrandColors.primary),
tertiary: BrandColors.tertiary.harmonizeWith(BrandColors.primary),
);
// 注入 MaterialApp
MaterialApp(
theme: ThemeData(
useMaterial3: true,
colorScheme: customScheme,
),
);
实现细节:Color.harmonizeWith 需传入主色作为参考,调和后对比度自动满足 WCAG AA,可在开发阶段通过 debugCheckHasMaterial3 验证。
2.4 调试与验证
使用 Flutter DevTools 的 "Theme Inspector" 面板检查色值。或输出调试日志:
void debugPrintColorScheme(ColorScheme scheme) {
debugPrint('Primary: ${scheme.primary.toHex()}');
debugPrint('OnPrimary: ${scheme.onPrimary.toHex()}');
debugPrint('ContrastRatio: ${ContrastRatio(scheme.primary, scheme.onPrimary).value}');
}
对比度应 ≥4.5(正常文本)或 ≥3.0(大文本)。若不符合,需调整 seed 色或手动修改某个色槽。
2.5 常见错误与性能优化
| 错误 | 表现 | 解决方案 |
|---|---|---|
使用 ColorScheme.light() 并直接传任意色值 | 深色模式失配,对比度不足 | 改用 fromSeed 或 ColorScheme.fromSwatch |
手动设置 surface 但未调和 | 按钮背景与文字颜色冲突 | 让系统自动派生 surface |
在运行时频繁重建 ColorScheme | UI 卡顿,帧率降低 | 缓存为静态常量,不要每次 build 新建 |
性能优化建议:
- 将
customScheme定义为static const避免重复计算调和算法。 - 如果应用有多个主题变体,使用
AnimatedTheme并在切换时保留ColorScheme缓存。 - Harmonized Colors 在 native 代码中执行,每秒可处理数百次,通常不是瓶颈。
2.6 结构总览:品牌色 → 调色板 → 最终 ColorScheme
注意:若品牌色本身对比度不足(如亮黄配亮白),Harmonized 系统会自动调整明度,可能导致最终 UI 颜色与品牌色存在视觉偏差。建议在品牌设计阶段就选择满足 WCAG AA 的主色。