Flutter Material 3设计语言详解

在 Flutter 中,Material 3(也称为 Material You)是 Google 最新的设计语言,它在 Material 2 的基础上进行了重大升级,提供了更个性化、更现代的设计体验。

Material 3 的主要特性

1. 动态色彩 (Dynamic Color)

Material 3 的核心特性之一是从用户壁纸中提取颜色主题。

Dart 复制代码
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material 3 Demo',
      theme: ThemeData(
        useMaterial3: true, // 启用 Material 3
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple, // 从种子颜色生成完整配色
        ),
      ),
      home: const MyHomePage(),
    );
  }
}

2. 更新的组件样式

按钮 (Buttons)
Dart 复制代码
class ButtonExamples extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        FilledButton(
          onPressed: () {},
          child: const Text('Filled Button'),
        ),
        const SizedBox(height: 10),
        FilledButton.tonal(
          onPressed: () {},
          child: const Text('Tonal Button'),
        ),
        const SizedBox(height: 10),
        OutlinedButton(
          onPressed: () {},
          child: const Text('Outlined Button'),
        ),
        const SizedBox(height: 10),
        TextButton(
          onPressed: () {},
          child: const Text('Text Button'),
        ),
      ],
    );
  }
}
导航栏 (Navigation Bar)
Dart 复制代码
class BottomNavigationExample extends StatefulWidget {
  const BottomNavigationExample({super.key});

  @override
  State<BottomNavigationExample> createState() =>
      _BottomNavigationExampleState();
}

class _BottomNavigationExampleState extends State<BottomNavigationExample> {
  int _selectedIndex = 0;

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Material 3 Navigation'),
      ),
      body: Center(
        child: Text('Selected Page: $_selectedIndex'),
      ),
      bottomNavigationBar: NavigationBar(
        selectedIndex: _selectedIndex,
        onDestinationSelected: _onItemTapped,
        destinations: const [
          NavigationDestination(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          NavigationDestination(
            icon: Icon(Icons.business),
            label: 'Business',
          ),
          NavigationDestination(
            icon: Icon(Icons.school),
            label: 'School',
          ),
        ],
      ),
    );
  }
}

3. 完整的 Material 3 主题配置

Dart 复制代码
ThemeData getMaterial3Theme(bool isDark) {
  return ThemeData(
    useMaterial3: true,
    colorScheme: isDark 
      ? ColorScheme.dark(
          primary: Colors.blue,
          secondary: Colors.cyan,
          background: Colors.grey[900]!,
        )
      : ColorScheme.light(
          primary: Colors.blue,
          secondary: Colors.cyan,
          background: Colors.white,
        ),
    // 或者使用 fromSeed 自动生成
    // colorScheme: ColorScheme.fromSeed(
    //   seedColor: Colors.blue,
    //   brightness: isDark ? Brightness.dark : Brightness.light,
    // ),
    
    // 文字主题
    textTheme: TextTheme(
      displayLarge: TextStyle(
        fontSize: 57,
        fontWeight: FontWeight.w400,
        color: isDark ? Colors.white : Colors.black87,
      ),
      titleLarge: TextStyle(
        fontSize: 22,
        fontWeight: FontWeight.w400,
        color: isDark ? Colors.white : Colors.black87,
      ),
      bodyLarge: TextStyle(
        fontSize: 16,
        fontWeight: FontWeight.w400,
        color: isDark ? Colors.white70 : Colors.black54,
      ),
    ),
    
    // 组件主题
    cardTheme: CardTheme(
      elevation: 1,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(12),
      ),
    ),
    
    elevatedButtonTheme: ElevatedButtonThemeData(
      style: ElevatedButton.styleFrom(
        padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(20),
        ),
      ),
    ),
  );
}

4. 响应式设计改进

Dart 复制代码
class AdaptiveLayoutExample extends StatelessWidget {
  const AdaptiveLayoutExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Adaptive Layout'),
      ),
      body: CustomScrollView(
        slivers: [
          // 大屏幕顶部的应用栏
          SliverAppBar.large(
            title: const Text('Large App Bar'),
          ),
          // 中等屏幕应用栏
          SliverAppBar.medium(
            title: const Text('Medium App Bar'),
          ),
          // 常规应用栏
          SliverAppBar(
            title: const Text('Regular App Bar'),
          ),
          // 内容区域
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) => ListTile(
                leading: Icon(
                  Icons.circle,
                  color: Theme.of(context).colorScheme.primary,
                ),
                title: Text('Item $index'),
                subtitle: Text('Subtitle for item $index'),
                trailing: IconButton(
                  icon: const Icon(Icons.more_vert),
                  onPressed: () {},
                ),
              ),
              childCount: 20,
            ),
          ),
        ],
      ),
    );
  }
}

启用 Material 3 的步骤

  1. 在 ThemeData 中设置 useMaterial3
Dart 复制代码
MaterialApp(
  theme: ThemeData(useMaterial3: true),
)
  1. 配置颜色方案
Dart 复制代码
// 方法1: 从种子颜色生成
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue)

// 方法2: 自定义完整配色
colorScheme: ColorScheme(
  primary: Colors.blue,
  secondary: Colors.cyan,
  // ... 其他颜色
)
  1. 更新组件使用新的 Widget

    • 使用 NavigationBar 替代 BottomNavigationBar

    • 使用 FilledButton 替代已弃用的按钮变体

    • 使用 SegmentedButton 进行分段选择

相关推荐
To_OC6 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
To_OC7 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode
GitLqr7 小时前
玩转 WebSocket:从原理到 Flutter 实战
websocket·网络协议·flutter
小林ixn7 小时前
从 ??= 到 onKeyDown:一个 React 组件的“自我修养”
前端·javascript·react.js
世人万千丶8 小时前
参数管理_Flutter在鸿蒙平台路由参数最佳实践
学习·flutter·华为·harmonyos·鸿蒙
এ慕ོ冬℘゜8 小时前
前端实战:jQuery 多条件联合搜索(标题模糊查询 + 日历时间段筛选)
前端·javascript·jquery
随心点儿9 小时前
js postMessage 实现跨域发送消息-应用示例
javascript·ecmascript·postmessage
kyriewen10 小时前
我让AI改一个bug——它偷偷动了5个我没让它碰的地方
前端·javascript·ai编程
gis开发之家15 小时前
《Vue3 从入门到大神35篇》Vue3 源码详解(五):effect 依赖收集原理——track 与 trigger 是如何工作的?
javascript·typescript·前端框架·vue3·vue3源码
zhazhazsy15 小时前
Flutter 多 Isolate 实战:搭建主 Isolate 数据与能力桥
flutter