flutter-theming by flutter/skills
npx skills add https://github.com/flutter/skills --skill flutter-theming通过将遗留的 Material 2 实现迁移到 Material 3、规范化组件主题、更新已弃用的按钮类以及调整 UI 惯用语以实现跨平台一致性,来更新和管理 Flutter 应用程序的样式。假设使用 Dart 的 Flutter 环境。
分析当前主题状态 审查现有的 Flutter 代码库,识别遗留的 Material 2 组件、已弃用的按钮类(FlatButton、RaisedButton、OutlineButton)以及过时的主题属性(例如 AppBarTheme 中的 accentColor、color)。停止并询问用户: "新的 Material 3 ColorScheme 的主要种子颜色是什么?应该优先为哪些目标平台(iOS、Android、Windows、macOS、Linux、Web)调整平台惯用语?"
决策逻辑:组件迁移 当遇到遗留组件时,使用以下决策树来确定替换方案:
* 如果 `BottomNavigationBar` -> 替换为 `NavigationBar`(使用 `NavigationDestination`)。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
* 如果 `Drawer` -> 替换为 `NavigationDrawer`(使用 `NavigationDrawerDestination`)。
* 如果 `ToggleButtons` -> 替换为 `SegmentedButton`(使用 `ButtonSegment` 和 `Set` 进行选择)。
* 如果 `FlatButton` -> 替换为 `TextButton`。
* 如果 `RaisedButton` -> 替换为 `ElevatedButton`(或使用 `FilledButton` 表示无海拔效果)。
* 如果 `OutlineButton` -> 替换为 `OutlinedButton`。
3. 实现应用范围的 Material 3 主题 使用 ColorScheme.fromSeed 定义全局 ThemeData。确保 useMaterial3 隐式或显式为 true。移除所有对已弃用强调色属性(accentColor、accentColorBrightness、accentTextTheme、accentIconTheme)的引用。
MaterialApp(
title: 'App Name',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: Brightness.light,
),
// 使用 colorScheme.secondary 替代 accentColor
),
darkTheme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: Brightness.dark,
),
),
home: const MyHomePage(),
);
4. 规范化组件主题 更新 ThemeData 中的所有组件主题定义,使用其对应的 *ThemeData 等效类。不要使用基础主题类进行配置。
* `cardTheme` -> `CardThemeData`
* `dialogTheme` -> `DialogThemeData`
* `tabBarTheme` -> `TabBarThemeData`
* `appBarTheme` -> `AppBarThemeData`(将 `color` 替换为 `backgroundColor`)
* `bottomAppBarTheme` -> `BottomAppBarThemeData`
* `inputDecorationTheme` -> `InputDecorationThemeData`
ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
appBarTheme: const AppBarThemeData(
backgroundColor: Colors.blue, // 不要使用 'color'
elevation: 4.0,
),
cardTheme: const CardThemeData(
elevation: 2.0,
),
);
5. 迁移按钮和按钮样式 替换遗留按钮。对于简单的覆盖,使用 styleFrom() 静态方法;对于依赖于状态的样式,使用带有 MaterialStateProperty 的 ButtonStyle。
// 使用 styleFrom 进行简单覆盖
TextButton(
style: TextButton.styleFrom(
foregroundColor: Colors.blue,
disabledForegroundColor: Colors.red,
),
onPressed: () {},
child: const Text('TextButton'),
)
// 使用 MaterialStateProperty 进行状态依赖的覆盖
OutlinedButton(
style: ButtonStyle(
side: MaterialStateProperty.resolveWith<BorderSide>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.pressed)) {
return const BorderSide(color: Colors.blue, width: 2);
}
return const BorderSide(color: Colors.grey, width: 1);
}
),
),
onPressed: () {},
child: const Text('OutlinedButton'),
)
6. 决策逻辑:平台惯用语 根据主机操作系统应用特定于平台的适配,以减少认知负荷并建立用户信任。
* **滚动条:** 如果是桌面平台 -> 设置 `thumbVisibility: true`(或 `alwaysShown`)。如果是移动平台 -> 使用默认的自动隐藏行为。
* **文本选择:** 如果文本是信息性的且不可交互 -> 使用 `SelectableText` 包裹,以允许在 Web/桌面端进行鼠标选择。
* **按钮顺序:** 如果是 Windows -> 将确认按钮放在左侧。如果是 macOS/Linux/Android/iOS -> 将确认按钮放在右侧。
// 平台感知的按钮排序
TextDirection btnDirection = Platform.isWindows
? TextDirection.rtl
: TextDirection.ltr;
Row(
children: [
const Spacer(),
Row(
textDirection: btnDirection,
children: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('OK'),
),
],
),
],
)
7. 验证与修复 扫描生成的代码,验证没有 FlatButton、RaisedButton、OutlineButton 或 ButtonTheme 类残留。验证 AppBarTheme 没有使用 color 属性。修复发现的任何实例。
ColorScheme 派生(例如 Theme.of(context).colorScheme.primary)。除非明确要求,否则不要硬编码十六进制颜色。FlatButton、RaisedButton 或 OutlineButton。accentColor、accentColorBrightness、accentTextTheme 或 accentIconTheme。请改用 colorScheme.secondary 和 colorScheme.onSecondary。ThemeData 时,始终为组件主题添加 Data 后缀(例如 CardThemeData,而不是 CardTheme)。AppBarTheme 或 AppBarThemeData 中绝不使用 color 属性;严格使用 backgroundColor。每周安装量
1.1K
仓库
GitHub 星标数
784
首次出现
2026年3月4日
安全审计
安装于
codex1.1K
cursor1.1K
opencode1.1K
gemini-cli1.1K
github-copilot1.1K
kimi-cli1.1K
Updates and manages Flutter application styling by migrating legacy Material 2 implementations to Material 3, normalizing component themes, updating deprecated button classes, and adapting UI idioms for cross-platform consistency. Assumes a Flutter environment using Dart.
Analyze Current Theme State Review the existing Flutter codebase to identify legacy Material 2 components, deprecated button classes (FlatButton, RaisedButton, OutlineButton), and outdated theme properties (e.g., accentColor, color in AppBarTheme). STOP AND ASK THE USER: "What is the primary seed color for the new Material 3 ColorScheme, and which target platforms (iOS, Android, Windows, macOS, Linux, Web) should be prioritized for platform idioms?"
Decision Logic: Component Migration When encountering legacy widgets, use the following decision tree to determine the replacement:
BottomNavigationBar -> REPLACE WITH NavigationBar (uses NavigationDestination).Drawer -> REPLACE WITH NavigationDrawer (uses NavigationDrawerDestination).ToggleButtons -> REPLACE WITH SegmentedButton (uses ButtonSegment and Set for selection).FlatButton -> REPLACE WITH .Implement App-Wide Material 3 Theme Define the global ThemeData using ColorScheme.fromSeed. Ensure useMaterial3 is implicitly or explicitly true. Remove all references to deprecated accent properties (accentColor, accentColorBrightness, accentTextTheme, accentIconTheme).
MaterialApp(
title: 'App Name',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: Brightness.light,
),
// Use colorScheme.secondary instead of accentColor
),
darkTheme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: Brightness.dark,
),
),
home: const MyHomePage(),
);
Normalize Component Themes Update all component theme definitions in ThemeData to use their *ThemeData equivalents. Do not use the base theme classes for configuration.
cardTheme -> CardThemeDatadialogTheme -> DialogThemeDatatabBarTheme -> TabBarThemeDataappBarTheme -> AppBarThemeData (Replace with )ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
appBarTheme: const AppBarThemeData(
backgroundColor: Colors.blue, // Do not use 'color'
elevation: 4.0,
),
cardTheme: const CardThemeData(
elevation: 2.0,
),
);
5. Migrate Buttons and Button Styles Replace legacy buttons. Use the styleFrom() static method for simple overrides, or ButtonStyle with MaterialStateProperty for state-dependent styling.
// Simple override using styleFrom
TextButton(
style: TextButton.styleFrom(
foregroundColor: Colors.blue,
disabledForegroundColor: Colors.red,
),
onPressed: () {},
child: const Text('TextButton'),
)
// State-dependent override using MaterialStateProperty
OutlinedButton(
style: ButtonStyle(
side: MaterialStateProperty.resolveWith<BorderSide>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.pressed)) {
return const BorderSide(color: Colors.blue, width: 2);
}
return const BorderSide(color: Colors.grey, width: 1);
}
),
),
onPressed: () {},
child: const Text('OutlinedButton'),
)
6. Decision Logic: Platform Idioms Apply platform-specific adaptations based on the host OS to reduce cognitive load and build user trust.
* **Scrollbars:** IF desktop platform -> Set `thumbVisibility: true` (or `alwaysShown`). IF mobile -> Use default auto-hiding behavior.
* **Text Selection:** IF text is informational and non-interactive -> Wrap in `SelectableText` to allow mouse selection on Web/Desktop.
* **Button Ordering:** IF Windows -> Place confirmation button on the LEFT. IF macOS/Linux/Android/iOS -> Place confirmation button on the RIGHT.
// Platform-aware button ordering
TextDirection btnDirection = Platform.isWindows
? TextDirection.rtl
: TextDirection.ltr;
Row(
children: [
const Spacer(),
Row(
textDirection: btnDirection,
children: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('OK'),
),
],
),
],
)
7. Validate-and-Fix Scan the generated code to verify that no FlatButton, RaisedButton, OutlineButton, or ButtonTheme classes remain. Verify that AppBarTheme does not use the color property. Fix any instances found.
ColorScheme (e.g., Theme.of(context).colorScheme.primary). Do not hardcode hex colors unless explicitly requested.FlatButton, RaisedButton, or OutlineButton.accentColor, accentColorBrightness, accentTextTheme, or accentIconTheme. Use colorScheme.secondary and instead.Weekly Installs
1.1K
Repository
GitHub Stars
784
First Seen
Mar 4, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex1.1K
cursor1.1K
opencode1.1K
gemini-cli1.1K
github-copilot1.1K
kimi-cli1.1K
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
TextButtonRaisedButton -> REPLACE WITH ElevatedButton (or FilledButton for no elevation).OutlineButton -> REPLACE WITH OutlinedButton.colorbackgroundColorbottomAppBarTheme -> BottomAppBarThemeDatainputDecorationTheme -> InputDecorationThemeDatacolorScheme.onSecondaryData to component themes when configuring ThemeData (e.g., CardThemeData, not CardTheme).color property in AppBarTheme or AppBarThemeData; strictly use backgroundColor.