Files
2026-09-04 15:22:20 +08:00

92 lines
3.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 【Demo】Seed 色板验证页(colorSchemeSeed 原理)
> 源文件:`lib/pages/demo/seed_palette_demo.dart` | 分类:基础布局
> 一句话:所有"没写死颜色"的 Material 组件,换一个 seed 就整体变色 —— 本页就是证据。
---
## 一、这个 Demo 解决什么问题
新手经常困惑:`colorSchemeSeed` 到底有什么用?为什么有的页面换主题变色,有的不变?
答案:**MaterialApp 的 `theme.colorSchemeSeed` 会自动生成整套 ColorScheme**,
页面里**不指定颜色**的 Material 组件(FilledButton/Checkbox/Switch/进度圈/聚焦输入框等)
颜色全部取自这套色板。本页把所有"不写死颜色"的组件摆在一起,换 seed 看整体变色。
---
## 二、怎么运行 / 演示内容
```bash
flutter run # 默认品牌 → 本页所有组件 SkyBlue 蓝
flutter run --dart-define=BRAND=chucai # 换品牌 → 本页所有组件变 Red 红
```
`--dart-define` 是编译期变量,由 `core/config/app_config.dart` 读取并决定 `seedColor`。
> 对照登录页为什么不变色:登录页所有颜色写死 `Color(0xFF3B82F6)` → 永远蓝色,不随主题走。
> **写死了就不跟主题,没写死才跟** —— 这是理解主题系统的关键。
---
## 三、核心知识点(新手向)
### 1. 色板怎么生成的
```dart
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. 取色值显示
```dart
String _hex(Color c) {
final v = c.toARGB32() & 0xFFFFFF; // Flutter 3.27+ 用 toARGB32 取色值
return '#${v.toRadixString(16).padLeft(6, '0').toUpperCase()}';
}
```
---
## 四、关键代码剖析
```dart
// 当前品牌主题(来自 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')),
```
---
## 五、踩坑记录
1. **`.w/.h` 的 widget 不能 const** —— 本页 CircularProgressIndicator 外面套的 SizedBox 就踩过
(`const_eval_extension_method` 编译错误);
2. `toARGB32()` 是新 API,旧的 `.value` 已废弃;
3. 别在页面里 `Theme.of(context).colorScheme.primary` 到处取 —— 组件不写颜色才是正道;
4. `--dart-define` 是编译期常量,热重载不生效,改品牌要重新 run。
---
## 六、扩展思考
- 二级主题(页面级细节)见 [theme_demo.md](theme_demo.md);
- 想精确控制色板:`ColorScheme.fromSeed(seedColor: x, primary: y, ...)` 手动覆盖某些槽位;
- 动态切换主题(运行时换色):Theme 局部覆盖或 AnimatedTheme,不依赖 --dart-define。