Skip to content
On this page

Flutter路由与导航

在Flutter中,导航是应用架构的重要组成部分,它允许用户在不同页面(在Flutter中称为"routes")之间进行切换。Flutter提供了多种导航方式,从简单的页面跳转到复杂的嵌套路由,本章将详细介绍Flutter中的导航机制。

基础导航

MaterialPageRoute

MaterialPageRoute是Flutter中最常用的路由,它实现了Material Design的页面切换动画。

dart
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Navigation Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '这是主页',
              style: Theme.of(context).textTheme.headlineSmall,
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SecondPage()),
                );
              },
              child: Text('跳转到第二页'),
            ),
          ],
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '这是第二页',
              style: Theme.of(context).textTheme.headlineSmall,
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: Text('返回上一页'),
            ),
          ],
        ),
      ),
    );
  }
}

CupertinoPageRoute

CupertinoPageRoute提供iOS风格的页面切换动画:

dart
class CupertinoNavigationDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Cupertino Navigation'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              CupertinoPageRoute(builder: (context) => CupertinoSecondPage()),
            );
          },
          child: Text('iOS风格导航'),
        ),
      ),
    );
  }
}

class CupertinoSecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('Cupertino Page'),
        previousPageTitle: 'Back',
      ),
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('iOS风格页面'),
            SizedBox(height: 20),
            CupertinoButton(
              child: Text('返回'),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        ),
      ),
    );
  }
}

参数传递

在页面之间传递数据是常见的需求,Flutter提供了多种方式来实现:

传递简单参数

dart
class DataPassingDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('数据传递演示')),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            final result = await Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => DataReceiverPage(
                  title: '来自首页的标题',
                  count: 42,
                ),
              ),
            );
            
            if (result != null) {
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('接收到返回数据: $result')),
              );
            }
          },
          child: Text('传递数据并等待返回'),
        ),
      ),
    );
  }
}

class DataReceiverPage extends StatelessWidget {
  final String title;
  final int count;

  const DataReceiverPage({Key? key, required this.title, required this.count}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('接收到的数字: $count'),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context, '返回的数据');
              },
              child: Text('返回并传递数据'),
            ),
          ],
        ),
      ),
    );
  }
}

传递复杂对象

dart
// 定义数据模型
class User {
  final String name;
  final int age;
  final String email;

  User({required this.name, required this.age, required this.email});

  // 为了在路由间传递,需要实现toString方法或使用json序列化
  @override
  String toString() {
    return 'User{name: $name, age: $age, email: $email}';
  }
}

class ObjectPassingDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('对象传递演示')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            final user = User(
              name: '张三',
              age: 25,
              email: 'zhangsan@example.com',
            );
            
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => UserProfilePage(user: user),
              ),
            );
          },
          child: Text('传递用户对象'),
        ),
      ),
    );
  }
}

class UserProfilePage extends StatelessWidget {
  final User user;

  const UserProfilePage({Key? key, required this.user}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('用户资料')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('姓名: ${user.name}', style: TextStyle(fontSize: 18)),
            SizedBox(height: 10),
            Text('年龄: ${user.age}', style: TextStyle(fontSize: 18)),
            SizedBox(height: 10),
            Text('邮箱: ${user.email}', style: TextStyle(fontSize: 18)),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: Text('返回'),
            ),
          ],
        ),
      ),
    );
  }
}

命名路由

命名路由提供了一种更结构化的方式来管理应用中的路由,特别适用于大型应用。

配置命名路由

dart
class NamedRouteApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Named Routes Demo',
      initialRoute: '/', // 初始路由
      routes: {
        // 命名路由映射
        '/': (context) => HomeNamedRoutePage(),
        '/profile': (context) => ProfileNamedRoutePage(),
        '/settings': (context) => SettingsNamedRoutePage(),
      },
    );
  }
}

class HomeNamedRoutePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('首页')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () {
                Navigator.pushNamed(context, '/profile');
              },
              child: Text('跳转到资料页'),
            ),
            SizedBox(height: 10),
            ElevatedButton(
              onPressed: () {
                Navigator.pushNamed(context, '/settings');
              },
              child: Text('跳转到设置页'),
            ),
          ],
        ),
      ),
    );
  }
}

class ProfileNamedRoutePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('资料页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('返回'),
        ),
      ),
    );
  }
}

class SettingsNamedRoutePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('设置页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('返回'),
        ),
      ),
    );
  }
}

带参数的命名路由

dart
class NamedRouteWithArgsApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Named Routes with Arguments',
      initialRoute: '/',
      routes: {
        '/': (context) => HomeWithArgsPage(),
        '/detail': (context) {
          // 从ModalRoute获取参数
          final Map<String, dynamic> args = ModalRoute.of(context)?.settings.arguments as Map<String, dynamic>;
          return DetailPage(
            title: args['title'],
            message: args['message'],
          );
        },
      },
    );
  }
}

class HomeWithArgsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('首页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(
              context,
              '/detail',
              arguments: {
                'title': '详情页面',
                'message': '这是从首页传递的消息',
              },
            );
          },
          child: Text('跳转到详情页'),
        ),
      ),
    );
  }
}

class DetailPage extends StatelessWidget {
  final String title;
  final String message;

  const DetailPage({Key? key, required this.title, required this.message}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(
        child: Padding(
          padding: EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(message, style: TextStyle(fontSize: 18)),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                child: Text('返回'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

导航器2.0(Router API)

Flutter 2.0引入了新的Router API,提供了更灵活的路由管理方式。

dart
import 'package:flutter/material.dart';

// 定义应用的路由状态
class AppRoutePath extends RouteSettings {
  final String location;
  final String? id;
  final String? action;

  AppRoutePath.home() : 
    location = '/',
    id = null,
    action = null,
    super(name: '/');

  AppRoutePath.details(this.id) : 
    location = '/details/$id',
    action = null,
    super(name: '/details');

  AppRoutePath.edit(this.id) : 
    location = '/details/$id/edit',
    action = 'edit',
    super(name: '/details');

  bool get isHomePage => location == '/';
  bool get isDetailsPage => id != null;
  bool get isEditing => action == 'edit';
}

// 定义路由信息解析器
class AppRouterDelegate extends RouterDelegate<AppRoutePath>
    with ChangeNotifier, PopNavigatorRouterDelegateMixin<AppRoutePath> {
  AppRouterDelegate() : navigatorKey = GlobalKey<NavigatorState>();

  final GlobalKey<NavigatorState> navigatorKey;

  String? _selectedBook;

  @override
  Widget build(BuildContext context) {
    return Navigator(
      key: navigatorKey,
      pages: [
        MaterialPage(
          child: HomeRouterPage(
            onBookTapped: _selectBook,
          ),
        ),
        if (_selectedBook != null)
          MaterialPage(
            child: DetailsRouterPage(
              id: _selectedBook!,
              onPopPage: () {
                _selectedBook = null;
                notifyListeners();
              },
            ),
          ),
      ],
      onPopPage: (route, result) {
        if (!route.didPop(result)) {
          return false;
        }
        
        _selectedBook = null;
        notifyListeners();
        return true;
      },
    );
  }

  void _selectBook(String id) {
    _selectedBook = id;
    notifyListeners();
  }

  @override
  Future<bool> popRoute() {
    if (_selectedBook == null) {
      return SynchronousFuture<bool>(false);
    }
    _selectedBook = null;
    notifyListeners();
    return SynchronousFuture<bool>(true);
  }

  @override
  AppRoutePath get currentConfiguration {
    if (_selectedBook != null) {
      return AppRoutePath.details(_selectedBook!);
    }
    return AppRoutePath.home();
  }

  @override
  Future<void> setNewRoutePath(AppRoutePath configuration) {
    if (configuration.isHomePage) {
      _selectedBook = null;
    } else {
      _selectedBook = configuration.id;
    }
    return SynchronousFuture<void>(null);
  }
}

// 路由信息解析器
class AppRouteInformationParser extends RouteInformationParser<AppRoutePath> {
  @override
  Future<AppRoutePath> parseRouteInformation(
      RouteInformation routeInformation) async {
    final uri = Uri.parse(routeInformation.location!);
    if (uri.pathSegments.isEmpty) {
      return AppRoutePath.home();
    }
    if (uri.pathSegments.length == 2) {
      return AppRoutePath.details(uri.pathSegments[1]);
    }
    return AppRoutePath.home();
  }

  @override
  RouteInformation? restoreRouteInformation(AppRoutePath configuration) {
    if (configuration.isHomePage) {
      return const RouteInformation(location: '/');
    }
    if (configuration.isDetailsPage) {
      return RouteInformation(location: '/details/${configuration.id}');
    }
    return null;
  }
}

class ModernRouterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Modern Router Demo',
      routerDelegate: AppRouterDelegate(),
      routeInformationParser: AppRouteInformationParser(),
    );
  }
}

class HomeRouterPage extends StatelessWidget {
  final Function(String) onBookTapped;

  const HomeRouterPage({Key? key, required this.onBookTapped}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final books = [
      {'id': '1', 'title': 'Flutter入门', 'author': '张三'},
      {'id': '2', 'title': 'Dart编程', 'author': '李四'},
      {'id': '3', 'title': '移动开发', 'author': '王五'},
    ];

    return Scaffold(
      appBar: AppBar(title: Text('图书列表')),
      body: ListView.builder(
        itemCount: books.length,
        itemBuilder: (context, index) {
          final book = books[index];
          return ListTile(
            title: Text(book['title']!),
            subtitle: Text('作者: ${book['author']}'),
            onTap: () => onBookTapped(book['id']!),
          );
        },
      ),
    );
  }
}

class DetailsRouterPage extends StatelessWidget {
  final String id;
  final Function() onPopPage;

  const DetailsRouterPage({Key? key, required this.id, required this.onPopPage}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('图书详情')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('图书ID: $id', style: TextStyle(fontSize: 18)),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: onPopPage,
              child: Text('返回'),
            ),
          ],
        ),
      ),
    );
  }
}

Tab导航

使用TabBar和TabBarView实现标签页导航:

dart
class TabNavigationDemo extends StatefulWidget {
  @override
  _TabNavigationDemoState createState() => _TabNavigationDemoState();
}

class _TabNavigationDemoState extends State<TabNavigationDemo> with TickerProviderStateMixin {
  late TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 3, vsync: this);
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Tab导航演示'),
        bottom: TabBar(
          controller: _tabController,
          tabs: [
            Tab(text: '首页', icon: Icon(Icons.home)),
            Tab(text: '搜索', icon: Icon(Icons.search)),
            Tab(text: '个人', icon: Icon(Icons.person)),
          ],
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: [
          HomePageTab(),
          SearchPageTab(),
          ProfilePageTab(),
        ],
      ),
    );
  }
}

class HomePageTab extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.home, size: 100, color: Colors.blue),
          Text('首页内容', style: TextStyle(fontSize: 24)),
        ],
      ),
    );
  }
}

class SearchPageTab extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.search, size: 100, color: Colors.green),
          Text('搜索内容', style: TextStyle(fontSize: 24)),
        ],
      ),
    );
  }
}

class ProfilePageTab extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.person, size: 100, color: Colors.orange),
          Text('个人内容', style: TextStyle(fontSize: 24)),
        ],
      ),
    );
  }
}

抽屉导航

使用Drawer实现侧滑菜单导航:

dart
class DrawerNavigationDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('抽屉导航演示'),
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            DrawerHeader(
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  CircleAvatar(
                    radius: 30,
                    backgroundColor: Colors.white,
                    child: Icon(Icons.person, size: 40),
                  ),
                  SizedBox(height: 10),
                  Text(
                    '用户名',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ),
            ListTile(
              leading: Icon(Icons.home),
              title: Text('首页'),
              onTap: () {
                Navigator.pop(context);
                // 处理首页逻辑
              },
            ),
            ListTile(
              leading: Icon(Icons.person),
              title: Text('个人资料'),
              onTap: () {
                Navigator.pop(context);
                // 处理个人资料逻辑
              },
            ),
            ListTile(
              leading: Icon(Icons.settings),
              title: Text('设置'),
              onTap: () {
                Navigator.pop(context);
                // 处理设置逻辑
              },
            ),
            Divider(),
            ListTile(
              leading: Icon(Icons.info),
              title: Text('关于'),
              onTap: () {
                Navigator.pop(context);
                // 处理关于逻辑
              },
            ),
          ],
        ),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('主页面内容', style: TextStyle(fontSize: 24)),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () => Scaffold.of(context).openDrawer(),
              child: Text('打开抽屉'),
            ),
          ],
        ),
      ),
    );
  }
}

导航历史管理

替换当前路由

dart
class NavigationHistoryDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('导航历史管理')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () {
                // 替换当前路由,用户按返回键时会跳过被替换的页面
                Navigator.pushReplacement(
                  context,
                  MaterialPageRoute(builder: (context) => ReplacementPage()),
                );
              },
              child: Text('替换当前页面'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                // 移除路由栈中的多个页面
                Navigator.pushNamedAndRemoveUntil(
                  context,
                  '/profile',
                  ModalRoute.withName('/'), // 移除到首页为止的所有页面
                );
              },
              child: Text('跳转并清除历史'),
            ),
          ],
        ),
      ),
    );
  }
}

class ReplacementPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('被替换的页面')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('这个页面会替换前一个页面'),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: Text('返回(会回到首页)'),
            ),
          ],
        ),
      ),
    );
  }
}

拦截返回按钮

dart
class BackButtonInterceptorDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        // 返回true允许返回,返回false阻止返回
        bool confirm = await showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: Text('确认退出'),
            content: Text('您确定要退出应用吗?'),
            actions: [
              TextButton(
                onPressed: () => Navigator.of(context).pop(false),
                child: Text('取消'),
              ),
              TextButton(
                onPressed: () => Navigator.of(context).pop(true),
                child: Text('确定'),
              ),
            ],
          ),
        );
        return confirm;
      },
      child: Scaffold(
        appBar: AppBar(title: Text('返回按钮拦截')),
        body: Center(
          child: Text('尝试按返回键'),
        ),
      ),
    );
  }
}

嵌套导航

在复杂应用中,可能需要在页面内部实现子导航:

dart
class NestedNavigationDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: Text('嵌套导航'),
          bottom: TabBar(
            tabs: [
              Tab(text: '列表'),
              Tab(text: '网格'),
            ],
          ),
        ),
        body: TabBarView(
          children: [
            ListViewPage(),
            GridViewPage(),
          ],
        ),
      ),
    );
  }
}

class ListViewPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: EdgeInsets.all(16.0),
      children: [
        for (int i = 1; i <= 10; i++)
          Card(
            child: ListTile(
              title: Text('项目 $i'),
              subtitle: Text('这是第 $i 个项目'),
              trailing: Icon(Icons.arrow_forward_ios),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => ItemDetailPage(itemId: i),
                  ),
                );
              },
            ),
          ),
      ],
    );
  }
}

class GridViewPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      padding: EdgeInsets.all(16.0),
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        crossAxisSpacing: 10,
        mainAxisSpacing: 10,
      ),
      itemCount: 8,
      itemBuilder: (context, index) {
        return Card(
          child: InkWell(
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => ItemDetailPage(itemId: index + 1),
                ),
              );
            },
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.grid_3x3, size: 50),
                  Text('项目 ${index + 1}'),
                ],
              ),
            ),
          ),
        );
      },
    );
  }
}

class ItemDetailPage extends StatelessWidget {
  final int itemId;

  const ItemDetailPage({Key? key, required this.itemId}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('项目 $itemId 详情')),
      body: Center(
        child: Padding(
          padding: EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(Icons.info, size: 80, color: Colors.blue),
              SizedBox(height: 20),
              Text(
                '项目 $itemId 详情页面',
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              ),
              SizedBox(height: 20),
              Text(
                '这里显示项目 $itemId 的详细信息',
                textAlign: TextAlign.center,
              ),
              SizedBox(height: 30),
              ElevatedButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                child: Text('返回'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

导航最佳实践

1. 使用命名路由进行组织

对于大型应用,建议使用命名路由来组织页面导航:

dart
class AppRoutes {
  static const String home = '/';
  static const String profile = '/profile';
  static const String settings = '/settings';
  static const String detail = '/detail';
  
  static Map<String, WidgetBuilder> get routes => {
    home: (context) => HomePage(),
    profile: (context) => ProfilePage(),
    settings: (context) => SettingsPage(),
  };
}

2. 合理使用导航器键

在某些情况下,可能需要全局访问导航器:

dart
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey,
      home: HomePage(),
    );
  }
}

// 在应用的任何地方导航
void navigateToProfile() {
  navigatorKey.currentState?.pushNamed('/profile');
}

3. 页面间数据传递的最佳实践

dart
// 定义路由参数类
class DetailPageArguments {
  final String title;
  final String content;
  final int id;

  DetailPageArguments({
    required this.title,
    required this.content,
    required this.id,
  });
}

// 在路由中使用
onGenerateRoute: (settings) {
  if (settings.name == '/detail') {
    final arguments = settings.arguments as DetailPageArguments;
    return MaterialPageRoute(
      builder: (context) => DetailPage(
        title: arguments.title,
        content: arguments.content,
        id: arguments.id,
      ),
    );
  }
  // ... 其他路由
  return null;
},

总结

Flutter提供了多种导航方式来满足不同场景的需求:

  1. 基础导航:使用MaterialPageRoute和CupertinoPageRoute进行基本页面跳转
  2. 参数传递:通过路由参数在页面间传递数据
  3. 命名路由:为大型应用提供结构化的路由管理
  4. 现代Router API:提供更灵活的路由控制
  5. Tab导航:实现标签页切换
  6. 抽屉导航:提供侧滑菜单
  7. 导航历史管理:控制页面栈行为

选择合适的导航方式对于构建用户体验良好的Flutter应用至关重要。在实际开发中,应根据应用的复杂度和需求选择最适合的导航方案。