关于 flutter-design
为 mobile-app-design-mastery 技能提供 Flutter 和 Dart 实现参考,通过主题、排版、间距和组件模式落实设计指导。
主要功能
- 01ThemeData 与 ColorScheme 模式
- 02TextTheme 排版指导
- 03可复用的间距常量
- 04BoxDecoration 示例
- 05ThemeExtension 模式
适用场景
- 01在 Flutter 界面中落实设计指导
- 02沿用项目现有主题配置
- 03构建样式一致的卡片和输入框
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ anilcancakir/ my-claude-code --skill flutter-design安装后在 Claude Code 中输入/flutter-design确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/extensions.mdtheming.mdwidgets.md详细介绍
Flutter 设计模式
为 mobile-app-design-mastery 技能提供的 Flutter/Dart 实现指南。将 Refactoring UI 原则转化为 Flutter 代码。
**前置条件:**此技能提供 Flutter 专用语法。有关移动应用设计理论和决策,请参阅
mobile-app-design-mastery技能。
⚠️ 重要:优先使用项目主题配置
创建新样式前,务必检查现有主题配置。
如果项目中有 ThemeData、AppColors、AppTextStyles 或类似配置,请使用它们:
// Check lib/core/theme/ or lib/config/
// Common patterns:
AppColors.primary
AppTextStyles.headline
AppSpacing.md
context.theme.colorScheme.primary
优先级顺序:
- 项目定义的主题(AppColors、AppTextStyles、自定义 ThemeExtension)
- 通过 Theme.of(context) 访问
- 硬编码值,仅作为最后手段
ThemeData 设置(Material 3)
MaterialApp(
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue, // Brand color
brightness: Brightness.light,
),
textTheme: _textTheme,
),
darkTheme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.dark,
),
textTheme: _textTheme,
),
);
颜色访问模式
// ✅ CORRECT: Use ColorScheme
final colors = Theme.of(context).colorScheme;
Container(color: colors.primary)
Text('Hello', style: TextStyle(color: colors.onSurface))
// ✅ With extension
extension BuildContextX on BuildContext {
ColorScheme get colors => Theme.of(this).colorScheme;
}
// Usage: context.colors.primary
// ❌ AVOID: Hardcoded colors
Container(color: Colors.blue) // Ignores theme
ColorScheme 角色:
| 角色 | 浅色模式 | 深色模式 | 使用场景 |
|---|---|---|---|
primary | 品牌色 | 较浅的品牌色 | CTA、激活状态 |
onPrimary | 白色 | 深色 | primary 上的文本 |
surface | 白色 | Gray-900 | 卡片、面板 |
onSurface | Gray-900 | 白色 | 正文 |
surfaceContainerHighest | Gray-100 | Gray-800 | 高层级表面 |
outline | Gray-400 | Gray-600 | 边框 |
error | 红色 | 浅红色 | 错误状态 |
字体排版(TextTheme)
Material 3 字体比例:
| 样式 | 大小(sp) | 使用场景 |
|---|---|---|
displayLarge | 57 | 主视觉文本 |
displayMedium | 45 | 大号展示文本 |
displaySmall | 36 | 展示文本 |
headlineLarge | 32 | 大标题 |
headlineMedium | 28 | 页面标题 |
headlineSmall | 24 | 分区标题 |
titleLarge | 22 | 卡片标题 |
titleMedium | 16 | 副标题 |
titleSmall | 14 | 小标题 |
bodyLarge | 16 | 强调正文 |
bodyMedium | 14 | 默认正文 |
bodySmall | 12 | 次要文本 |
labelLarge | 14 | 按钮 |
labelMedium | 12 | 标签 |
labelSmall | 11 | 说明文字 |
// ✅ CORRECT: Use TextTheme
Text('Title', style: Theme.of(context).textTheme.headlineMedium)
// With extension
extension BuildContextX on BuildContext {
TextTheme get textTheme => Theme.of(this).textTheme;
}
// Usage: context.textTheme.bodyMedium
间距系统(4dp 网格)
创建可复用的间距常量:
abstract class AppSpacing {
static const double xs = 4;
static const double sm = 8;
static const double md = 12;
static const double base = 16;
static const double lg = 24;
static const double xl = 32;
static const double xxl = 48;
// SizedBox shortcuts
static const SizedBox gapXs = SizedBox(height: xs, width: xs);
static const SizedBox gapSm = SizedBox(height: sm, width: sm);
static const SizedBox gapMd = SizedBox(height: md, width: md);
static const SizedBox gapBase = SizedBox(height: base, width: base);
static const SizedBox gapLg = SizedBox(height: lg, width: lg);
}
// Usage
Padding(padding: EdgeInsets.all(AppSpacing.base))
Column(children: [widget1, AppSpacing.gapMd, widget2])
BoxDecoration 模式
卡片(平面)
Container(
decoration: BoxDecoration(
color: colors.surface,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: colors.outline.withOpacity(0.2)),
),
)
卡片(浮起)
Container(
decoration: BoxDecoration(
color: colors.surface,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
)
输入框
Container(
decoration: BoxDecoration(
color: colors.surface,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: colors.outline),
),
)
阴影比例
abstract class AppShadows {
static List<BoxShadow> sm = [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 4,
offset: const Offset(0, 1),
),
];
static List<BoxShadow> md = [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: 8,
offset: const Offset(0, 2),
),
];
static List<BoxShadow> lg = [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 16,
offset: const Offset(0, 4),
),
];
static List<BoxShadow> xl = [
BoxShadow(
color: Colors.black.withOpacity(0.15),
blurRadius: 24,
offset: const Offset(0, 8),
),
];
}
// Usage
Container(decoration: BoxDecoration(boxShadow: AppShadows.md))
反模式
// ❌ NEVER
Colors.blue // Hardcoded, ignores theme
TextStyle(fontSize: 16) // Not from TextTheme
SizedBox(height: 17) // Off 4dp grid
EdgeInsets.only(top: 20, left: 8) // Asymmetric without reason
// ✅ INSTEAD
context.colors.primary
context.textTheme.bodyLarge
SizedBox(height: 16) // On grid
EdgeInsets.all(16) // Symmetric
参考文件
| 主题 | 文件 |
|---|---|
| ThemeData 与 ColorScheme | theming.md |
| Widget 配方 | widgets.md |
| ThemeExtension 模式 | extensions.md |
评论
支持 Markdown