Flutter中GoRouter实现无限导航并保留BottomNavigationBar的方案咨询
核心思路
要同时实现无限嵌套的导航循环(post→user→post…)和保留BottomNavigationBar,关键是把需要复用的post/user路由定义抽离出来,作为StatefulShellBranch的共享子路由挂载,既避免重复代码,又确保所有页面都处于底部栏所在的导航栈中。
实现代码
首先抽离复用的路由逻辑,通过循环引用实现无限嵌套结构:
// 复用的Post路由,包含嵌套的User及后续循环路由 final postRoute = GoRoute( path: 'post/:postId', pageBuilder: (context, state) { final postId = state.pathParameters['postId']!; return MaterialPage(child: PostScreen(postId: postId)); }, routes: [ // 嵌套的User路由 GoRoute( path: 'user/:userId', pageBuilder: (context, state) { final userId = state.pathParameters['userId']!; return MaterialPage(child: UserScreen(userId: userId)); }, routes: [ postRoute, // 循环引用,实现post→user→post的无限导航 // FeedCollectionUser路由 GoRoute( path: 'feedcollectionuser/:collectionId', pageBuilder: (context, state) { final collectionId = state.pathParameters['collectionId']!; return MaterialPage(child: FeedCollectionUserScreen(id: collectionId)); }, routes: [ postRoute, // 继续嵌套Post,保持循环结构 ], ), ], ), ], );
然后在StatefulShellRoute的分支中挂载这个复用路由:
GoRouter createRouter(BuildContext context) { final authBloc = context.read<AuthBloc>(); return GoRouter( navigatorKey: _rootNavigatorKey, debugLogDiagnostics: true, initialLocation: '/home', routes: <RouteBase>[ StatefulShellRoute.indexedStack( builder: (context, state, navigationShell) { return ScaffoldWithNavBar( currentLocation: state.uri.toString(), navigationShell: navigationShell, userIdFromAuth: authBloc.state.user!.uid, appBar: null, ); }, branches: <StatefulShellBranch>[ // Home分支 StatefulShellBranch( routes: <RouteBase>[ GoRoute( path: '/home', pageBuilder: (context, state) { return MaterialPage(child: HomeScreen()); }, routes: [ postRoute, // 挂载复用的Post路由 ], ), ], ), // Feed分支 StatefulShellBranch( routes: <RouteBase>[ GoRoute( path: '/feed', pageBuilder: (context, state) { return MaterialPage(child: FeedScreen()); }, routes: [ postRoute, // 同样挂载复用路由 ], ), ], ), ], ), ], ); }
方案优势
- 路径简洁且符合需求:路由结构完全匹配你期望的嵌套层级,比如
/home/post/123/user/456/post/789 - 组件/路由复用:只需要定义一次
post/user路由逻辑,即可在Home和Feed分支中共享 - 保留BottomNavigationBar:所有页面都处于
StatefulShell的分支导航栈内,底部栏始终可见 - 完整导航历史:每次跳转都会添加到当前分支的导航栈,返回操作按顺序退栈,完美支持无限循环跳转
补充说明
如果需要跨分支跳转(比如从Home的post跳转到Feed的post),直接使用context.go('/feed/post/${targetPostId}')即可,此时会自动切换到Feed分支并加载对应页面,底部栏也会同步切换到Feed标签。
内容的提问来源于stack exchange,提问作者Kathar6
相关产品推荐
相关产品推荐

