flutter架 构项目基础
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# 【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。
|
||||
Reference in New Issue
Block a user