关于 flutter-native-ui
flutter-native-ui 是依据当前 Flutter 和 Dart 文档构建及检查界面的技能,面向 Flutter 开发者,强调沿用现有设计系统并选择合适的平台组件。
主要功能
- 01依据官方文档指导界面设计
- 02沿用现有主题与导航
- 03指导 Material 和 Cupertino 模式
- 04涵盖响应式布局与控件
- 05要求分析器和视觉验证
适用场景
- 01为现有 Flutter 应用构建页面
- 02选择自适应控件与导航方式
- 03检查空白、加载和错误状态
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ thesimpleapp/ flutter-app-skills --skill flutter-native-ui安装后在 Claude Code 中输入/flutter-native-ui确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/animations.mdcontrols.mdicons-and-media.mdlayout.mdnavigation.mdstorage.mdtheming.mdvisual-effects.md详细介绍
Flutter 原生 UI
所有 UI 选择都应以当前 Flutter 和 Dart 文档为依据,而不是 React Native 或 Expo 的模式。检查 flutter --version。官方来源:docs.flutter.dev、api.flutter.dev、dart.dev、m3.material.io,以及来自 flutter.dev 的 pub.dev 软件包。
如果项目已有设计系统、设计令牌或路由器,请在其基础上扩展。不要另行创建第二套主题或第二个导航器。
如果组件读取的是自定义的 ThemeExtension、品牌设计令牌文件,或使用 *Pressable 而不是 Material ink,请停止并遵循 flutter-custom-design-system。不要为了套用标准 Material 3 而“修复”该应用。
参考资料
只阅读所需的文件:
references/
navigation.md go_router, tabs, sheets, dialogs, transitions
theming.md ColorScheme, TextTheme, light/dark, Cupertino
layout.md SafeArea, MediaQuery.*Of, breakpoints, slivers
controls.md Adaptive constructors, buttons, fields, pickers
animations.md Implicit first, Hero, M3 motion, lists
icons-and-media.md Icons.adaptive, images, camera, audio, video
visual-effects.md Elevation, blur, gradients
storage.md Preferences, secure storage, files, SQL
设计系统
选择一种应用外壳并贯彻到底。
| 产品 | 根组件 | 外壳 |
|---|---|---|
| 跨平台(默认) | MaterialApp / MaterialApp.router | Material 3 + .adaptive() 控件 |
| iOS 优先 | CupertinoApp / CupertinoApp.router | Cupertino 组件 + HIG 间距 |
| 现有应用 | 沿用现有应用的设置 | 不要为了证明某个观点而重设整个应用的样式 |
Flutter 会自动适配操作系统行为(滚动物理效果、返回手势、文本编辑、触觉反馈),但不会自动切换标签栏、应用栏或信息架构。这些都需要明确选择。请参阅平台适配。
除 .adaptive() 构造函数和 Icons.adaptive 外,不要在同一界面混用 Material 和 Cupertino 组件。
自 Flutter 3.16 起,Material 3 已是默认设置。切勿设置 useMaterial3: false。也不要把 useMaterial3: true 当作可选开关传入。
导入(Flutter 3.47+)
Material 和 Cupertino 已作为独立的 1.0 软件包发布:material_ui 和 cupertino_ui。在 3.47 中,SDK 内的副本仍可使用,预计将在 2026 年秋季的 stable 版本中弃用。
- **现有项目:**沿用项目中已有的导入方式。
- 新建 3.47+ 应用,或按要求迁移时:
flutter pub add material_ui
# only if you build Cupertino chrome:
flutter pub add cupertino_ui
dart fix --apply --code=migrate_design_widgets
这会将 package:flutter/material.dart 改写为 package:material_ui/material_ui.dart,并将 package:flutter/cupertino.dart 改写为 package:cupertino_ui/cupertino_ui.dart。
如果 pubspec.yaml 没有更新,请运行 flutter pub add material_ui(以及 cupertino_ui),然后再次运行 dart fix --apply。
仍导入 SDK 库的旧版软件包组件需要桥接:
MaterialApp(
builder: (context, child) => MaterialUiCompatibilityBridge(child: child!),
)
本地化:使用 material_ui 中的 localizationsDelegates: GlobalMaterialLocalizations.delegates(包含 Cupertino 和 Widgets)。迁移后,不要继续保留 flutter_localizations 的 GlobalMaterialLocalizations / GlobalCupertinoLocalizations。
构建屏幕
- 阅读现有主题、路由器和附近的屏幕,并沿用这些约定。
- 选择脚手架:
Scaffold+AppBar/SliverAppBar(Material),或CupertinoPageScaffold+CupertinoNavigationBar/CupertinoSliverNavigationBar(Cupertino)。 - 将页面标题放在应用栏/导航栏中,不要在正文顶部使用自定义
Text。 - 将
SafeArea用于正文周围,而不是整个Scaffold周围(AppBar已会绘制到状态栏下方)。嵌套的SafeArea会折叠;不要自行读取MediaQuery.padding来添加内边距。 - 可滚动页面:使用
CustomScrollView+ slivers,或ListView.builder。表单使用ListView/CustomScrollView,不要使用可能溢出的裸Column。 - 颜色和字体来自
ColorScheme.of(context)和TextTheme.of(context)。不要直接使用Colors.blue,也不要单独设置fontSize: 13。 - 交互控件要使用
const ValueKey<String>('kebab-name')。 - 修改后:先热重载,再验证(见“验证”)。
硬性规则
主题与颜色
- 使用
ColorScheme.fromSeed构建配色方案。搭配使用theme、darkTheme和themeMode。 - 通过
ColorScheme.of(context)和TextTheme.of(context)读取令牌(等同于Theme.of(context).colorScheme/.textTheme)。 - 使用 M3 角色:
primary/onPrimary、surface/onSurface、surfaceContainer*、outline、error。不要使用primarySwatch或accentColor。 - Cupertino 颜色使用
CupertinoColors/CupertinoDynamicColor,并通过CupertinoDynamicColor.resolve(color, context)解析。
布局
- 使用
MediaQuery.sizeOf/paddingOf/viewInsetsOf/viewPaddingOf/textScalerOf/platformBrightnessOf/highContrastOf/accessibleNavigationOf。绝不要使用MediaQuery.of(context).size(它会在 MediaQuery 每次变化时触发重建)。 - 使用
Row/Column/Flex的spacing设置间距。使用Wrap的spacing+runSpacing。不要在每个子项之间都随意插入SizedBox。 - 根据窗口尺寸而非设备类型进行布局。绝不要用
Platform.isIOS来选择手机或平板布局。绝不要在应用根部使用OrientationBuilder。断点:紧凑<600,中等600–839,扩展≥840(M3 窗口尺寸类别)。 - 不要锁定屏幕方向。不要使用
flutter_screenutil或设计像素缩放器。
组件(新代码)
| 使用 | 不要使用 |
|---|---|
FilledButton、FilledButton.tonal、OutlinedButton、TextButton | 将 ElevatedButton 作为主要操作按钮,RaisedButton、FlatButton |
NavigationBar + NavigationDestination | BottomNavigationBar |
在较大宽度下使用 NavigationRail / NavigationDrawer | 在桌面端拉伸手机导航栏 |
SegmentedButton | ToggleButtons |
DropdownMenu | DropdownButton / DropdownButtonFormField |
MenuAnchor / MenuBar | 为新菜单使用 PopupMenuButton |
SearchAnchor / SearchBar | 在应用栏中自制搜索 TextField |
Card.filled / Card.outlined | 随意组合 Container + BoxShadow 制作卡片 |
ListView.builder / slivers | ListView(children: hugeList) |
Switch.adaptive、Slider.adaptive、Checkbox.adaptive、Radio.adaptive、CircularProgressIndicator.adaptive、RefreshIndicator.adaptive、AlertDialog.adaptive、showAdaptiveDialog | 对这些原生操作系统控件使用不区分平台的 Material 控件 |
导航
- 新建多屏应用:使用
go_router+MaterialApp.router/CupertinoApp.router。官方文档不推荐使用MaterialApp.routes命名路由。 - 对于已有的
Navigator.push应用:除非要求迁移,否则继续使用Navigator。 - 需要保留各标签页独立堆栈的标签页:使用
StatefulShellRoute.indexedStack。 - 底部弹出层和对话框保持无页面路由状态(
showModalBottomSheet、showAdaptiveDialog)。除非需要支持深层链接,否则不要将每个弹出层都做成 GoRoute。 - 全屏模态框:使用
fullscreenDialog: true(iOS 呈现方式),或使用带有该页面标记的GoRoute。
Dart / 组件
- 使用
const构造函数。优先拆分为小组件,不要写一个 400 行的build。 - 文件名使用
snake_case.dart。类型使用PascalCase。交互键使用 kebab-case 字符串。 - 对用户可能需要复制的值,使用
SelectableText或放在SelectionArea祖先组件下。 - 表格数字:
fontFeatures: const [FontFeature.tabularFigures()]。 - 仅用于调试的跳转芯片和预填内容必须放在
kDebugMode下,并且仍须经过真实的身份验证流程。 - 不要为发布屏幕添加 GetX、
flutter_screenutil、用于 Chrome 图标的 FontAwesome 或新的状态管理包。
不要照搬 Expo/RN 的习惯
- 不要使用
StyleSheet、process.env.EXPO_OS、SafeAreaView、CSSboxShadow或 kebab-case 源文件。 - 不要使用
flex: 1样式映射——请使用Expanded/Flexible。 - 不要通过
expo-image使用 SF Symbols。请使用Icons.adaptive/CupertinoIcons。
验证
编辑应用成功,并不代表 UI 工作已经完成。
- 确保你修改的文件通过分析器检查(
dart analyze/flutter analyze)。 - 对正在运行的应用执行热重载。如果修改了
main、路由或全局主题,则执行热重启。 - 查看运行中的画面(截图、Widget 预览或项目的可视化循环)。过时的画面不能作为依据。
- 对于独立 Widget:使用
package:flutter/widget_previews.dart中的@Preview(在 3.47 中已稳定)。请参阅 Widget Previewer。 - 检查你修改的屏幕在空状态、加载状态、错误状态和键盘打开时的表现,以及任何读取相同状态的其他路由。