flutter:语义化颜色ColorScheme

是什么

ColorSchemeFlutter(特别是 Material 3)主题系统的核心类,用来统一管理 App 的所有语义化颜色。它不是单纯的颜色集合,而是 带有角色意义的颜色系统,每个属性代表 UI 中一个特定的语义场景。这样Flutter 的内置组件(如 AppBarButtonCard 等)就能根据语义自动使用合适的颜色。

一个 ColorScheme 大致分为以下几类:

  1. 主色(Primary / Secondary / Tertiary)系列 → 用于突出品牌、强调内容。
  2. 错误色(Error)系列 → 用于错误提示、警告。
  3. 表面(Surface)系列 → 各种容器、背景。
  4. 文字与图标(OnXxx)系列 → 表示在某种背景色上的前景色。
  5. 辅助属性(outline / shadow / scrim / inverse 等) → 用于边框、遮罩、反转场景。
  6. Fixed & Container 扩展色(Material 3 引入)→ 提供更多层级的颜色,用于不同层次的 UI。

属性

常见属性

属性 作用 常见使用场景
brightness 明暗模式(light / dark),决定整体基调 Material 自动适配文本/图标对比度
primary 主色,品牌色、重点按钮颜色 AppBarFABButton
onPrimary 主色上的前景色 主色按钮的文字、图标
primaryContainer 主色容器色,主色的扩展背景 Card、选中状态背景
onPrimaryContainer 主色容器上的前景色 容器里的文字、图标
secondary 次要色,辅助强调 Chip、辅助按钮
onSecondary 次要色上的前景色 次要按钮的文字
secondaryContainer 次要容器色 卡片背景、分组背景
onSecondaryContainer 次要容器前景色 次要容器里的文字
tertiary 第三强调色,用于特殊功能 装饰性元素、图表高亮
onTertiary 第三强调色上的前景色 第三色上的文字
tertiaryContainer 第三色容器 对话框、底部抽屉
onTertiaryContainer 第三色容器上的前景色 文字、图标
error 错误色 表单错误、警告提示
onError 错误背景上的前景色 错误按钮文字
errorContainer 错误容器背景 错误提示卡片
onErrorContainer 错误容器上的前景色 错误描述文字
surface 表面色,UI 背景主色 Scaffold 背景、卡片
onSurface 表面上的前景色 页面文字、图标
onSurfaceVariant 表面变体上的前景色 次级文字、禁用文字
surfaceTint 表面着色(M3 新特性) 卡片高亮、层次感
outline 轮廓色 边框、分割线
outlineVariant 边框弱化色 次级边框、禁用边框
shadow 阴影颜色 卡片、浮动按钮投影
scrim 遮罩颜色 弹窗、模态背景
inverseSurface 反转表面色 夜间模式 / 对比背景
inversePrimary 反转主色 深色模式下的主色替代

Material 3 扩展属性

属性 作用 常见使用场景
primaryFixed / primaryFixedDim 固定的主色(不随明暗变化) 固定强调区域
onPrimaryFixed / onPrimaryFixedVariant 固定主色上的前景色 文字、图标
secondaryFixed / secondaryFixedDim 固定的次色 辅助区域
tertiaryFixed / tertiaryFixedDim 固定的第三色 装饰区域
surfaceDim / surfaceBright 表面不同亮度层级 暗背景 / 亮背景
surfaceContainerLowest → Highest 多层次容器背景 多层卡片、分区背景

brightness

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _isDark = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blue,
          brightness: Brightness.light, // 明亮模式
        ),
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blue,
          brightness: Brightness.dark, // 暗黑模式
        ),
        useMaterial3: true,
      ),
      themeMode: _isDark ? ThemeMode.dark : ThemeMode.light,
      home: Scaffold(
        appBar: AppBar(title: const Text("ColorScheme.brightness 示例")),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text("Hello Brightness!", style: TextStyle(fontSize: 32)),
              const SizedBox(height: 20),
              Text(
                _isDark ? "当前:Dark 模式" : "当前:Light 模式",
                style: const TextStyle(fontSize: 20),
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () => setState(() => _isDark = !_isDark),
          child: const Icon(Icons.brightness_6),
        ),
      ),
    );
  }
}

ThemeData 里的 brightness

这是 Flutter 较早的写法,在 Material 2 时代主要靠它区分浅色/深色主题。

它本质上是一个 快捷方式,影响整个 ThemeData 的默认颜色。

但是,它的颗粒度比较粗:

  • 设置 Brightness.dark 就会自动应用一组「暗色」的默认颜色(比如背景黑、文字白)。
  • 你不能对每个角色(如 primaryonBackgroundsurface)分别定制。

ColorScheme 里的 brightness

Material 3 开始,官方推荐用 ColorScheme 作为唯一颜色来源

ColorScheme 更精细,包含了完整的色彩体系(primary、secondary、background、surface、error 等等)。

brightnessColorScheme 里起到 基调作用

  • Brightness.lightprimarybackground 等都会自动生成浅色系。
  • Brightness.dark → 同一套色板会生成深色版本。

这样,主题的所有组件(按钮、卡片、文字、背景)都从同一个 ColorScheme 派生,风格统一。

两者区别

属性 时代/背景 控制范围 灵活性 推荐使用场景
ThemeData.brightness Material 2 遗留写法 整个主题整体的明暗 粗粒度,不能细调 老项目、快速区分亮/暗
ColorScheme.brightness Material 3 推荐方案 影响整个 ColorScheme 的生成 精细、全局一致 新项目,需完整配色系统

创建 ColorScheme 的方式

创建方式 用法 适合场景 是否推荐
ColorScheme.fromSeed 自动生成整套配色 你只提供一个种子颜色(如蓝色),其余自动生成 ✅ 最推荐(Material 3 风格)
ColorScheme.light() 创建一套浅色主题的默认颜色 想快速得到一套浅色默认颜色 ✅ 常用
ColorScheme.dark() 创建一套深色主题的默认颜色 想快速得到一套深色默认颜色 ✅ 常用
ColorScheme(...) 构造函数(手动指定) 自己定义每一个颜色 完全自定义配色 ✅ 高级用法(定制主题)

ColorScheme.fromSeed

final colorScheme = ColorScheme.fromSeed(
  seedColor: Colors.teal,
  brightness: Brightness.light,
);
  • 只传一个 seedColor,它会帮你自动生成整套颜色。

    如何理解「成套的颜色」

    Material Design 3 里,一个主题不是单一的颜色,而是一整套互相关联的颜色(primarysecondarytertiarysurfaceerror 等)。

    如果你只传一个 seedColor,Flutter 会基于这个颜色 自动生成一套和谐的色板,确保按钮、背景、文本等颜色搭配合理。

    就像你给设计师说:“主色是蓝色”,设计师就会自动帮你配好次要色、容器色、对比色。

  • 默认遵循 Material 3 动态色彩规范

  • 也可以加上 brightness: Brightness.dark 来生成深色版本。

**优点:**①一致性强;②自动生成搭配良好的配色;③支持浅色/深色两套

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue), // 只传蓝色
        useMaterial3: true,
      ),
      home: const ColorSchemeDemo(),
    );
  }
}

class ColorSchemeDemo extends StatelessWidget {
  const ColorSchemeDemo({super.key});

  @override
  Widget build(BuildContext context) {
    final scheme = Theme.of(context).colorScheme;

    return Scaffold(
      appBar: AppBar(title: const Text("ColorScheme.fromSeed 示例")),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            Container(
              height: 60,
              width: double.infinity,
              color: scheme.primary,
              child: Center(
                child: Text(
                  "Primary",
                  style: TextStyle(color: scheme.onPrimary),
                ),
              ),
            ),
            const SizedBox(height: 10),
            Container(
              height: 60,
              width: double.infinity,
              color: scheme.secondary,
              child: Center(
                child: Text(
                  "Secondary",
                  style: TextStyle(color: scheme.onSecondary),
                ),
              ),
            ),
            const SizedBox(height: 10),
            Container(
              height: 60,
              width: double.infinity,
              color: scheme.tertiary,
              child: Center(
                child: Text(
                  "Tertiary",
                  style: TextStyle(color: scheme.onTertiary),
                ),
              ),
            ),
            const SizedBox(height: 10),
            Container(
              height: 60,
              width: double.infinity,
              color: scheme.error,
              child: Center(
                child: Text("Error", style: TextStyle(color: scheme.onError)),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

效果说明

  • 我们只传了 Colors.blue,但是 Flutter 自动生成了:
    • primary 蓝色
    • secondary 比较柔和的蓝紫色
    • tertiary 辅助的对比色
    • error 红色(系统内置的警示色)
    • surfacebackground 等浅色搭配
  • 整个 UI 的 对比色(onPrimary、onSecondary)也自动生成,保证文字在背景上可见。

ColorScheme.light / ColorScheme.dark

final lightScheme = ColorScheme.light();
final darkScheme  = ColorScheme.dark();

这是 Flutter 提供的默认浅色 / 深色配色方案。

可以传参数来自定义某些颜色:

final customLight = ColorScheme.light(
  primary: Colors.deepPurple,
  secondary: Colors.orange,
);

优点:

  • 快速得到一套配色
  • 适合不使用 Material 3 动态色的情况

ColorScheme(…) 构造函数

final customScheme = const ColorScheme(
  brightness: Brightness.light,
  primary: Color(0xff00214a),
  onPrimary: Colors.white,
  secondary: Color(0xff192232),
  onSecondary: Colors.white,
  error: Color(0xffb00020),
  onError: Colors.white,
  background: Color(0xfff9f9ff),
  onBackground: Colors.black,
  surface: Colors.white,
  onSurface: Colors.black,
  // 还要继续写所有必填字段……
);

特点:

  • 所有字段都要你自己填,没填会报错
  • 用于完全掌控配色方案
  • 一般用于企业设计系统、自定义主题

×

喜欢就点赞,疼爱就打赏