Flutter 导航深度解析:从入门到精通
Flutter 导航深度解析从入门到精通掌握 Flutter 导航的每一种模式构建流畅的用户体验。一、导航的核心概念作为一名追求像素级还原的 UI 匠人我深知导航是应用的骨架。Flutter 提供了多种导航方式从简单的Navigator.push到复杂的声明式路由每一种都有其适用场景。二、命令式导航1. 基础导航// 跳转到新页面 Navigator.push( context, MaterialPageRoute(builder: (context) DetailPage()), ); // 返回上一页 Navigator.pop(context); // 替换当前页面 Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) NewPage()), ); // 清除栈并跳转到新页面 Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) HomePage()), (route) false, // 清除所有历史 );2. 传递参数// 跳转时传递参数 Navigator.push( context, MaterialPageRoute( builder: (context) DetailPage(itemId: 123), ), ); // 接收参数 class DetailPage extends StatelessWidget { final String itemId; DetailPage({required this.itemId}); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(详情)), body: Center(child: Text(Item ID: $itemId)), ); } } // 返回时传递数据 Navigator.pop(context, result_data); // 接收返回数据 final result await Navigator.push( context, MaterialPageRoute(builder: (context) DetailPage()), );3. 自定义路由动画class FadeRoute extends PageRouteBuilder { final Widget page; FadeRoute({required this.page}) : super( pageBuilder: (context, animation, secondaryAnimation) page, transitionsBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition( opacity: animation, child: child, ); }, ); } // 使用 Navigator.push(context, FadeRoute(page: DetailPage()));三、声明式导航Navigator 2.01. 基础结构class MyApp extends StatefulWidget { override _MyAppState createState() _MyAppState(); } class _MyAppState extends StateMyApp { String _selectedItem ; bool _showDetail false; override Widget build(BuildContext context) { return MaterialApp( home: Navigator( pages: [ MaterialPage( key: ValueKey(HomePage), child: HomePage( onItemSelected: (item) { setState(() { _selectedItem item; _showDetail true; }); }, ), ), if (_showDetail) MaterialPage( key: ValueKey(DetailPage_$_selectedItem), child: DetailPage( itemId: _selectedItem, onBack: () { setState(() _showDetail false); }, ), ), ], onPopPage: (route, result) { if (!route.didPop(result)) return false; setState(() _showDetail false); return true; }, ), ); } }2. 使用 Routerclass MyApp extends StatelessWidget { override Widget build(BuildContext context) { return MaterialApp.router( routerDelegate: MyRouterDelegate(), routeInformationParser: MyRouteInformationParser(), ); } } // 路由信息 class RouteInformation { final String? itemId; RouteInformation({this.itemId}); } // 路由解析器 class MyRouteInformationParser extends RouteInformationParserRouteInformation { override FutureRouteInformation parseRouteInformation( RouteInformation routeInformation, ) async { final uri Uri.parse(routeInformation.location ?? /); if (uri.pathSegments.length 2 uri.pathSegments[0] item) { return RouteInformation(itemId: uri.pathSegments[1]); } return RouteInformation(); } override RouteInformation restoreRouteInformation(RouteInformation configuration) { if (configuration.itemId ! null) { return RouteInformation(location: /item/${configuration.itemId}); } return RouteInformation(location: /); } } // 路由委托 class MyRouterDelegate extends RouterDelegateRouteInformation with ChangeNotifier, PopNavigatorRouterDelegateMixinRouteInformation { final GlobalKeyNavigatorState navigatorKey GlobalKeyNavigatorState(); String? _selectedItem; set selectedItem(String? value) { _selectedItem value; notifyListeners(); } override RouteInformation get currentConfiguration { return RouteInformation(itemId: _selectedItem); } override Widget build(BuildContext context) { return Navigator( key: navigatorKey, pages: [ MaterialPage( key: ValueKey(HomePage), child: HomePage( onItemSelected: (item) { selectedItem item; }, ), ), if (_selectedItem ! null) MaterialPage( key: ValueKey(DetailPage_$_selectedItem), child: DetailPage( itemId: _selectedItem!, onBack: () { selectedItem null; }, ), ), ], onPopPage: (route, result) { if (!route.didPop(result)) return false; selectedItem null; return true; }, ); } override Futurevoid setNewRoutePath(RouteInformation configuration) async { _selectedItem configuration.itemId; } }四、GoRouter简化导航import package:go_router/go_router.dart; final router GoRouter( initialLocation: /, routes: [ GoRoute( path: /, builder: (context, state) HomePage(), routes: [ GoRoute( path: item/:id, builder: (context, state) { final id state.pathParameters[id]!; return DetailPage(itemId: id); }, ), ], ), GoRoute( path: /settings, builder: (context, state) SettingsPage(), ), ], ); // 使用 class MyApp extends StatelessWidget { override Widget build(BuildContext context) { return MaterialApp.router( routerConfig: router, ); } } // 导航 context.go(/); context.go(/item/123); context.push(/settings);五、底部导航与嵌套导航class MainPage extends StatefulWidget { override _MainPageState createState() _MainPageState(); } class _MainPageState extends StateMainPage { int _currentIndex 0; final _pages [ HomeTab(), SearchTab(), ProfileTab(), ]; override Widget build(BuildContext context) { return Scaffold( body: IndexedStack( index: _currentIndex, children: _pages, ), bottomNavigationBar: BottomNavigationBar( currentIndex: _currentIndex, onTap: (index) setState(() _currentIndex index), items: [ BottomNavigationBarItem( icon: Icon(Icons.home), label: 首页, ), BottomNavigationBarItem( icon: Icon(Icons.search), label: 搜索, ), BottomNavigationBarItem( icon: Icon(Icons.person), label: 我的, ), ], ), ); } }六、最佳实践选择合适的方式简单应用用命令式复杂应用用声明式状态管理导航状态应该与应用状态同步URL 支持Web 应用要确保每个页面都有对应的 URL过渡动画保持一致的页面过渡效果导航是用户的空间地图清晰的导航让探索成为享受。#flutter #navigation #routing #mobile #architecture