flutter架 构项目基础

This commit is contained in:
崔宝新
2026-09-04 15:22:20 +08:00
parent 70967229d0
commit 0c5aee59c0
265 changed files with 35484 additions and 0 deletions
+257
View File
@@ -0,0 +1,257 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:new_learn/core/config/app_config.dart';
/// ============================================================
/// 【SeedPaletteDemo】Seed 色板 —— 验证"主题 seed 是否生效"的演示页
///
/// 一、原理:
/// MaterialApp 的 theme.colorSchemeSeed(来自 AppConfig.theme.seedColor)
/// 会自动生成整套 ColorScheme(primary/secondary/tertiary/...)。
/// 页面里【不指定颜色】的 Material 组件,颜色全部取自这套色板:
/// FilledButton/Checkbox/Switch/Radio/进度圈/聚焦输入框 等。
/// 所以换一个品牌(seed 不同),整页组件整体变色 —— 这就是
/// "seed 驱动全局 Material 色板" 的直接证明。
///
/// 二、怎么验证:
/// flutter run → 本页所有组件是 SkyBlue 蓝
/// flutter run --dart-define=BRAND=chucai → 本页所有组件变 Red 红
///
/// 三、对比理解(对照登录页为什么不变色):
/// 本页组件【没写死颜色】→ 跟随 seed 变;
/// 登录页所有颜色写死 Color(0xFF3B82F6) 等 → 永远蓝色,不随主题走。
/// ============================================================
class SeedPaletteDemoPage extends StatefulWidget {
const SeedPaletteDemoPage({super.key});
@override
State<SeedPaletteDemoPage> createState() => _SeedPaletteDemoPageState();
}
class _SeedPaletteDemoPageState extends State<SeedPaletteDemoPage> {
final _focusController = TextEditingController();
bool _checked = true;
bool _switched = true;
int _chipSelected = 1;
@override
void dispose() {
// 输入框 controller 必须在 dispose 释放(防内存泄漏)
_focusController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final brandTheme = AppConfig.theme;
return Scaffold(
appBar: AppBar(
title: const Text('Seed 色板'),
centerTitle: true,
),
body: ListView(
padding: EdgeInsets.all(16.w),
children: [
// ─── ① 当前品牌 / seed 信息卡 ───
_sectionTitle('① 当前生效的 seed'),
Container(
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.r),
border: Border.all(color: const Color(0xFFEEF1F5)),
),
child: Row(
children: [
// seed 色块:就是 AppConfig.theme.seedColor
Container(
width: 56.w,
height: 56.h,
decoration: BoxDecoration(
color: brandTheme.seedColor,
borderRadius: BorderRadius.circular(12.r),
),
),
SizedBox(width: 16.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppConfig.appName,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: const Color(0xFF333333),
),
),
SizedBox(height: 4.h),
Text(
'主题 ${brandTheme.name} · seed '
'${_hex(brandTheme.seedColor)}',
style: TextStyle(
fontSize: 12.sp,
color: const Color(0xFF999999),
),
),
],
),
),
],
),
),
SizedBox(height: 24.h),
// ─── ② 组件区说明 ───
_sectionTitle('② 下列组件【未写死颜色】'),
_tipCard('它们的颜色全部取自 colorSchemeSeed 自动生成的色板。'
'跑不同品牌包,下面所有组件整体变色。'),
// ─── ③ 按钮组 ───
_sectionTitle('按钮(默认取 primary)'),
Row(
children: [
FilledButton(
onPressed: () {},
child: const Text('FilledButton'),
),
SizedBox(width: 12.w),
OutlinedButton(
onPressed: () {},
child: const Text('OutlinedButton'),
),
SizedBox(width: 12.w),
TextButton(
onPressed: () {},
child: const Text('TextButton'),
),
],
),
SizedBox(height: 24.h),
// ─── ④ 勾选 / 开关 / 选择标签 ───
_sectionTitle('勾选 / 开关 / 选择标签(选中色取自 seed 色板)'),
Row(
children: [
Checkbox(
value: _checked,
onChanged: (v) => setState(() => _checked = v!),
),
const Text('Checkbox'),
SizedBox(width: 24.w),
Switch(
value: _switched,
onChanged: (v) => setState(() => _switched = v),
),
SizedBox(width: 12.w),
const Text('Switch'),
SizedBox(width: 24.w),
ChoiceChip(
label: const Text('选项1'),
selected: _chipSelected == 1,
onSelected: (_) => setState(() => _chipSelected = 1),
),
SizedBox(width: 12.w),
ChoiceChip(
label: const Text('选项2'),
selected: _chipSelected == 2,
onSelected: (_) => setState(() => _chipSelected = 2),
),
],
),
SizedBox(height: 24.h),
// ─── ⑤ 进度指示器 ───
_sectionTitle('进度指示器(默认取 primary)'),
Row(
children: [
// 注意:这里不能写 const —— .w/.h 是 ScreenUtil 扩展方法,
// extension 方法不允许出现在 const 表达式里(const_eval_extension_method)
SizedBox(
width: 32.w,
height: 32.h,
child: const CircularProgressIndicator(strokeWidth: 3),
),
SizedBox(width: 20.w),
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.circular(4.r),
child: const LinearProgressIndicator(value: 0.6),
),
),
],
),
SizedBox(height: 24.h),
// ─── ⑥ 聚焦输入框 ───
_sectionTitle('聚焦输入框(边框取 primary)'),
_tipCard('点进输入框,光标 + 聚焦边框颜色 = 当前 seed 主色。'),
TextField(
controller: _focusController,
decoration: InputDecoration(
labelText: '点击聚焦看边框颜色',
border: const OutlineInputBorder(),
),
),
SizedBox(height: 24.h),
// ─── ⑦ 验证提示 ───
_sectionTitle('⑦ 怎么看到变化'),
Container(
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: const Color(0xFFE8F0FE),
borderRadius: BorderRadius.circular(12.r),
),
child: Text(
'flutter run --dart-define=BRAND=chucai\n'
'→ 本页所有组件变成红色系。\n\n'
'flutter run(默认爱学蝶变)\n'
'→ 恢复 SkyBlue 蓝色系。',
style: TextStyle(fontSize: 13.sp, color: const Color(0xFF3B82F6)),
),
),
],
),
);
}
/// 段落小标题
Widget _sectionTitle(String text) {
return Padding(
padding: EdgeInsets.only(bottom: 10.h),
child: Text(
text,
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: const Color(0xFF333333),
),
),
);
}
/// 灰色提示卡
Widget _tipCard(String text) {
return Container(
padding: EdgeInsets.all(12.w),
margin: EdgeInsets.only(bottom: 12.h),
decoration: BoxDecoration(
color: const Color(0xFFF7F8FA),
borderRadius: BorderRadius.circular(10.r),
),
child: Text(
text,
style: TextStyle(fontSize: 12.sp, color: const Color(0xFF666666)),
),
);
}
/// Color → #RRGGBB 显示(Flutter 3.27+ 用 toARGB32 取色值)
String _hex(Color c) {
final v = c.toARGB32() & 0xFFFFFF;
return '#${v.toRadixString(16).padLeft(6, '0').toUpperCase()}';
}
}