flutter-theming

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Goal

目标

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.
通过将旧版Material 2实现迁移到Material 3、规范组件主题、更新已弃用的按钮类、适配UI习惯用语以实现跨平台一致性,来更新和管理Flutter应用的样式。本教程假设你使用的是基于Dart的Flutter开发环境。

Instructions

操作指引

  1. 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?"
  2. Decision Logic: Component Migration When encountering legacy widgets, use the following decision tree to determine the replacement:
    • IF
      BottomNavigationBar
      -> REPLACE WITH
      NavigationBar
      (uses
      NavigationDestination
      ).
    • IF
      Drawer
      -> REPLACE WITH
      NavigationDrawer
      (uses
      NavigationDrawerDestination
      ).
    • IF
      ToggleButtons
      -> REPLACE WITH
      SegmentedButton
      (uses
      ButtonSegment
      and
      Set
      for selection).
    • IF
      FlatButton
      -> REPLACE WITH
      TextButton
      .
    • IF
      RaisedButton
      -> REPLACE WITH
      ElevatedButton
      (or
      FilledButton
      for no elevation).
    • IF
      OutlineButton
      -> REPLACE WITH
      OutlinedButton
      .
  3. 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
    ).
    dart
    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(),
    );
  4. 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
      ->
      CardThemeData
    • dialogTheme
      ->
      DialogThemeData
    • tabBarTheme
      ->
      TabBarThemeData
    • appBarTheme
      ->
      AppBarThemeData
      (Replace
      color
      with
      backgroundColor
      )
    • bottomAppBarTheme
      ->
      BottomAppBarThemeData
    • inputDecorationTheme
      ->
      InputDecorationThemeData
    dart
    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.
    dart
    // 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.
    dart
    // 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.
  1. 分析当前主题状态 检查现有的Flutter代码库,找出旧版Material 2组件、已弃用的按钮类(
    FlatButton
    RaisedButton
    OutlineButton
    )以及过时的主题属性(例如
    AppBarTheme
    中的
    accentColor
    color
    )。 停下并询问用户: "新的Material 3 ColorScheme的主种子色是什么,平台适配习惯用语应该优先适配哪些目标平台(iOS、Android、Windows、macOS、Linux、Web)?"
  2. 决策逻辑:组件迁移 遇到旧版组件时,使用以下决策树确定替换方案:
    • 如果是
      BottomNavigationBar
      -> 替换为
      NavigationBar
      (使用
      NavigationDestination
      )。
    • 如果是
      Drawer
      -> 替换为
      NavigationDrawer
      (使用
      NavigationDrawerDestination
      )。
    • 如果是
      ToggleButtons
      -> 替换为
      SegmentedButton
      (使用
      ButtonSegment
      Set
      实现选择功能)。
    • 如果是
      FlatButton
      -> 替换为
      TextButton
    • 如果是
      RaisedButton
      -> 替换为
      ElevatedButton
      (无阴影需求可使用
      FilledButton
      )。
    • 如果是
      OutlineButton
      -> 替换为
      OutlinedButton
  3. 实现全局Material 3主题 使用
    ColorScheme.fromSeed
    定义全局
    ThemeData
    ,确保
    useMaterial3
    隐式或显式为true。移除所有对已弃用的accent相关属性的引用(
    accentColor
    accentColorBrightness
    accentTextTheme
    accentIconTheme
    )。
    dart
    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(),
    );
  4. 规范组件主题
    ThemeData
    中所有组件主题定义更新为对应的
    *ThemeData
    类型,不要使用基础主题类进行配置。
    • cardTheme
      ->
      CardThemeData
    • dialogTheme
      ->
      DialogThemeData
    • tabBarTheme
      ->
      TabBarThemeData
    • appBarTheme
      ->
      AppBarThemeData
      (将
      color
      替换为
      backgroundColor
    • bottomAppBarTheme
      ->
      BottomAppBarThemeData
    • inputDecorationTheme
      ->
      InputDecorationThemeData
    dart
    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. 迁移按钮与按钮样式 替换旧版按钮。简单样式覆盖可以使用
    styleFrom()
    静态方法,状态相关样式则使用搭配
    MaterialStateProperty
    ButtonStyle
    dart
    // 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. 决策逻辑:平台适配习惯用语 根据宿主操作系统应用平台特定适配,降低用户认知成本,建立用户信任。
    • 滚动条: 如果是桌面平台 -> 设置
      thumbVisibility: true
      (或
      alwaysShown
      )。如果是移动端 -> 使用默认的自动隐藏行为。
    • 文本选择: 如果是信息类非交互文本 -> 包裹在
      SelectableText
      中,支持Web/桌面端鼠标选择。
    • 按钮排序: 如果是Windows系统 -> 将确认按钮放在左侧。如果是macOS/Linux/Android/iOS -> 将确认按钮放在右侧
    dart
    // 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. 验证与修复 扫描生成的代码,确认没有残留
    FlatButton
    RaisedButton
    OutlineButton
    ButtonTheme
    类。确认
    AppBarTheme
    没有使用
    color
    属性,修复所有发现的问题。

Constraints

约束条件

  • Single Source of Truth: All colors must be derived from the
    ColorScheme
    (e.g.,
    Theme.of(context).colorScheme.primary
    ). Do not hardcode hex colors unless explicitly requested.
  • No Legacy Buttons: Never output
    FlatButton
    ,
    RaisedButton
    , or
    OutlineButton
    .
  • No Accent Properties: Never use
    accentColor
    ,
    accentColorBrightness
    ,
    accentTextTheme
    , or
    accentIconTheme
    . Use
    colorScheme.secondary
    and
    colorScheme.onSecondary
    instead.
  • Component Theme Suffixes: Always append
    Data
    to component themes when configuring
    ThemeData
    (e.g.,
    CardThemeData
    , not
    CardTheme
    ).
  • AppBar Background: Never use the
    color
    property in
    AppBarTheme
    or
    AppBarThemeData
    ; strictly use
    backgroundColor
    .
  • 唯一数据源: 所有颜色必须派生自
    ColorScheme
    (例如
    Theme.of(context).colorScheme.primary
    )。除非明确要求,否则不要硬编码十六进制颜色。
  • 禁止使用旧版按钮: 绝对不要输出
    FlatButton
    RaisedButton
    OutlineButton
  • 禁止使用Accent相关属性: 绝对不要使用
    accentColor
    accentColorBrightness
    accentTextTheme
    accentIconTheme
    ,请改用
    colorScheme.secondary
    colorScheme.onSecondary
  • 组件主题后缀: 配置
    ThemeData
    时,组件主题必须始终加上
    Data
    后缀(例如使用
    CardThemeData
    而非
    CardTheme
    )。
  • AppBar背景配置: 绝对不要在
    AppBarTheme
    AppBarThemeData
    中使用
    color
    属性,严格使用
    backgroundColor