如何通过非底部导航栏按钮切换go_router底部导航栏状态
解决GoRouter中跨分支跳转时底部导航不切换的问题
要实现从Section A页面跳转到Section B详情页时同步切换底部导航状态,你需要使用StatefulNavigationShell的goBranch方法,而非直接调用context.push。该方法会同时切换底部导航的选中分支,并导航到目标页面。
具体修改步骤
- 在
HomePage中获取当前的StatefulNavigationShell实例 - 调用
goBranch方法,传入目标分支的索引(Section B对应索引1),并指定initialLocation为目标详情页路径/b/detail
修改HomePage中的按钮代码:
ElevatedButton( onPressed: () { final shell = StatefulNavigationShell.of(context); shell.goBranch( 1, initialLocation: '/b/detail', ); }, child: const Text("Move to B Detail Page"), ),
同理,若需从Section B页面跳转到Section A详情页,可使用同样逻辑:
ElevatedButton( onPressed: () { final shell = StatefulNavigationShell.of(context); shell.goBranch( 0, initialLocation: '/a/detail', ); }, child: const Text("Move to A Detail Page"), ),
原方法无效原因
直接调用context.push("/b/detail")仅会在当前导航栈中添加新页面,不会触发StatefulShellRoute的分支切换逻辑,底部导航的currentIndex仍保持原分支索引。而goBranch方法会主动切换分支,并将指定路径作为该分支的初始导航位置,从而同步更新底部导航的选中状态。
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; void main() { runApp(MaterialApp.router( routerConfig: router, )); } final GlobalKey<NavigatorState> _rootNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'root'); final GlobalKey<NavigatorState> _homeNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'a'); final GlobalKey<NavigatorState> _settingsNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'b'); final GoRouter router = GoRouter( navigatorKey: _rootNavigatorKey, initialLocation: '/a', routes: <RouteBase> [ StatefulShellRoute.indexedStack( builder: (context, state, navigationShell){ return ScaffoldWithNavBar(navigationShell: navigationShell,); }, branches: <StatefulShellBranch>[ StatefulShellBranch( navigatorKey: _homeNavigatorKey, routes: <RouteBase>[ GoRoute( path: '/a', builder: (context, state) => const HomePage(pageTitle: "A",), routes: [ GoRoute( path: 'detail', builder: (context, state) => const DetailPage(pageTitle: "A",), ), ], ), ], ), StatefulShellBranch( navigatorKey: _settingsNavigatorKey, routes: [ GoRoute( path: '/b', builder: (context, state) => const HomePage(pageTitle: "B",), routes: [ GoRoute( path: 'detail', builder: (context, state) => const DetailPage(pageTitle: "B",), ), ], ), ], ), ], ), ] ); class ScaffoldWithNavBar extends StatelessWidget { const ScaffoldWithNavBar({ required this.navigationShell, Key? key, }) : super(key: key ?? const ValueKey<String>('ScaffoldWithNavBar')); final StatefulNavigationShell navigationShell; @override Widget build(BuildContext context) { return Scaffold( body: navigationShell, bottomNavigationBar: BottomNavigationBar( items: const <BottomNavigationBarItem>[ BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Section A'), BottomNavigationBarItem(icon: Icon(Icons.work), label: 'Section B'), ], currentIndex: navigationShell.currentIndex, onTap: (int index) => navigationShell.goBranch(index), ), ); } } class HomePage extends StatelessWidget { const HomePage({ super.key, required this.pageTitle, }); final String pageTitle; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: true, title: Text("$pageTitle Home Page"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ElevatedButton( onPressed: () { final shell = StatefulNavigationShell.of(context); shell.goBranch( 0, initialLocation: '/a/detail', ); }, child: const Text("Move to A Detail Page"), ), ElevatedButton( onPressed: () { final shell = StatefulNavigationShell.of(context); shell.goBranch( 1, initialLocation: '/b/detail', ); }, child: const Text("Move to B Detail Page"), ), ] ), ), ); } } class DetailPage extends StatelessWidget { const DetailPage({ super.key, required this.pageTitle, }); final String pageTitle; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: true, title: Text("$pageTitle Detail Page"), ), ); } }
内容的提问来源于stack exchange,提问作者sukekyo000
相关产品推荐
相关产品推荐

