3.4 KiB
3.4 KiB
【Demo】Seed 色板验证页(colorSchemeSeed 原理)
源文件:
lib/pages/demo/seed_palette_demo.dart| 分类:基础布局 一句话:所有"没写死颜色"的 Material 组件,换一个 seed 就整体变色 —— 本页就是证据。
一、这个 Demo 解决什么问题
新手经常困惑:colorSchemeSeed 到底有什么用?为什么有的页面换主题变色,有的不变?
答案:MaterialApp 的 theme.colorSchemeSeed 会自动生成整套 ColorScheme,
页面里不指定颜色的 Material 组件(FilledButton/Checkbox/Switch/进度圈/聚焦输入框等)
颜色全部取自这套色板。本页把所有"不写死颜色"的组件摆在一起,换 seed 看整体变色。
二、怎么运行 / 演示内容
flutter run # 默认品牌 → 本页所有组件 SkyBlue 蓝
flutter run --dart-define=BRAND=chucai # 换品牌 → 本页所有组件变 Red 红
--dart-define 是编译期变量,由 core/config/app_config.dart 读取并决定 seedColor。
对照登录页为什么不变色:登录页所有颜色写死
Color(0xFF3B82F6)→ 永远蓝色,不随主题走。 写死了就不跟主题,没写死才跟 —— 这是理解主题系统的关键。
三、核心知识点(新手向)
1. 色板怎么生成的
ThemeData(colorSchemeSeed: seedColor)
Material 的 ColorScheme.fromSeed 算法从种子色推出一整套颜色: primary / onPrimary / secondary / tertiary / error / surface 等几十个语义色。 组件默认取语义色:按钮取 primary、进度圈取 primary、Checkbox 选中取 primary……
2. 本页验证清单(全部未写死颜色)
- 按钮组:FilledButton / OutlinedButton / TextButton;
- Checkbox / Switch / ChoiceChip 选中态;
- CircularProgressIndicator / LinearProgressIndicator;
- TextField 聚焦边框 + 光标。
3. 取色值显示
String _hex(Color c) {
final v = c.toARGB32() & 0xFFFFFF; // Flutter 3.27+ 用 toARGB32 取色值
return '#${v.toRadixString(16).padLeft(6, '0').toUpperCase()}';
}
四、关键代码剖析
// 当前品牌主题(来自 AppConfig,启动时由 --dart-define 决定)
final brandTheme = AppConfig.theme;
// 展示 seed 色块 + 品牌信息
Container(
width: 56.w, height: 56.h,
decoration: BoxDecoration(color: brandTheme.seedColor, ...),
),
Text('主题 ${brandTheme.name} · seed ${_hex(brandTheme.seedColor)}'),
// 一个不写颜色的组件(示例)—— 它的颜色来自当前 seed 色板
FilledButton(onPressed: () {}, child: const Text('FilledButton')),
五、踩坑记录
.w/.h的 widget 不能 const —— 本页 CircularProgressIndicator 外面套的 SizedBox 就踩过 (const_eval_extension_method编译错误);toARGB32()是新 API,旧的.value已废弃;- 别在页面里
Theme.of(context).colorScheme.primary到处取 —— 组件不写颜色才是正道; --dart-define是编译期常量,热重载不生效,改品牌要重新 run。
六、扩展思考
- 二级主题(页面级细节)见 theme_demo.md;
- 想精确控制色板:
ColorScheme.fromSeed(seedColor: x, primary: y, ...)手动覆盖某些槽位; - 动态切换主题(运行时换色):Theme 局部覆盖或 AnimatedTheme,不依赖 --dart-define。