第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 实现流程

  1. 提取品牌色值(HEX 或 RGB)。
  2. 在 Material3 主题构造时,使用 ColorScheme.fromSeed 或手动构造 ColorScheme。
  3. (可选)对特定色值调用 Color.harmonizeWith 进行调和。
  4. 将自定义 ColorScheme 注入 MaterialApp.theme。
  5. 在 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
在运行时频繁重建 ColorSchemeUI 卡顿,帧率降低缓存为静态常量,不要每次 build 新建

性能优化建议:

  • 将 customScheme 定义为 static const 避免重复计算调和算法。
  • 如果应用有多个主题变体,使用 AnimatedTheme 并在切换时保留 ColorScheme 缓存。
  • Harmonized Colors 在 native 代码中执行,每秒可处理数百次,通常不是瓶颈。

2.6 结构总览:品牌色 → 调色板 → 最终 ColorScheme

ColorScheme 配置流程 品牌色 → 调和 → 应用 Primary (品牌蓝) Secondary (品牌绿) Tertiary (品牌橙) Harmonized 调色板 色轮旋转 + 明度缩放 产出 0–200 色调 ColorScheme Surface / On Contrast 验证

注意:若品牌色本身对比度不足(如亮黄配亮白),Harmonized 系统会自动调整明度,可能导致最终 UI 颜色与品牌色存在视觉偏差。建议在品牌设计阶段就选择满足 WCAG AA 的主色。