如何在切换底部导航栏时保活通过Navigator.push()打开的子页面
底部导航切换时保活子页面的实现方案
这个需求可通过给每个底部导航tab维护独立导航栈的方式实现,核心是避免所有tab共用全局Navigator,以下是具体实现逻辑:
实现步骤
- 给每个tab创建独立
Navigator实例
每个导航tab对应专属的导航栈,tab切换时不会销毁对应栈内的路由页面,示例代码如下:
// 先定义每个tab的根页面 final List<Widget> tabRootPages = [ const ScreenA(), const ScreenB(), const ScreenC(), ]; // 封装独立导航栈的生成方法 Widget _buildTabNavigator(int tabIndex) { return Navigator( key: GlobalKey<NavigatorState>(), onGenerateRoute: (settings) { return MaterialPageRoute( builder: (context) => tabRootPages[tabIndex], ); }, ); }
- 用
IndexedStack封装所有tab的导航栈IndexedStack会默认保留所有子组件的状态,切换tab时不会重新构建对应导航栈,自然不会销毁已经push的子页面:
int currentTabIndex = 0; @override Widget build(BuildContext context) { return Scaffold( body: IndexedStack( index: currentTabIndex, children: [ _buildTabNavigator(0), _buildTabNavigator(1), _buildTabNavigator(2), ], ), bottomNavigationBar: BottomNavigationBar( currentIndex: currentTabIndex, onTap: (index) { setState(() { currentTabIndex = index; }); }, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: "页面A"), BottomNavigationBarItem(icon: Icon(Icons.search), label: "页面B"), BottomNavigationBarItem(icon: Icon(Icons.person), label: "页面C"), ], ), ); }
- 子页面跳转逻辑无需修改
在Screen A中调用Navigator.push(context, MaterialPageRoute(builder: (context) => const ScreenChildA()))时,会自动使用Screen A所属tab的独立导航栈完成跳转,切换其他tab再切回时,已经打开的Screen Child A会完整保留。
可选优化
如果需要实现点击当前tab自动回退到根页面的逻辑,可通过对应tab的GlobalKey<NavigatorState>获取导航栈状态,调用maybePop()直到返回根页面即可。
内容的提问来源于stack exchange,提问作者Darmawan Z.
相关产品推荐
相关产品推荐

