Flutter应用中BottomNavigationBar跳转消失问题的解决方法
你遇到的问题根源很直接:用pushReplacement跳转时,直接把包含底部导航栏的父页面替换成了WorkoutsPage,新页面本身没嵌套底部导航,自然就看不到了。下面给你两种实用的解决思路:
思路一:直接切换底部导航的选中索引(推荐)
既然你的底部导航本来就是通过_selectedIndex切换页面,那提交按钮触发时,直接修改这个索引就行,根本不需要用Navigator跳转。
实现步骤:
- 给底部导航所在的页面(比如叫MainPage)定义一个GlobalKey,用来跨页面调用状态方法:
// 在MainPage外部定义全局key final GlobalKey<MainPageState> mainPageKey = GlobalKey<MainPageState>(); class MainPage extends StatefulWidget { const MainPage({super.key}) : super(key: mainPageKey); @override MainPageState createState() => MainPageState(); }
- 在MainPage的State里,添加修改索引的方法:
class MainPageState extends State<MainPage> { int _selectedIndex = 0; // 页面列表,对应底部导航的选项 final List<Widget> _pages = const [HomeScreen(), WorkoutsPage()]; // 暴露修改索引的方法 void switchToPage(int index) { setState(() { _selectedIndex = index; }); } @override Widget build(BuildContext context) { return Scaffold( body: _pages[_selectedIndex], bottomNavigationBar: BottomNavigationBar( currentIndex: _selectedIndex, onTap: switchToPage, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'), BottomNavigationBarItem(icon: Icon(Icons.fitness_center), label: '训练'), ], ), ); } }
- 提交按钮的点击事件里,直接调用这个方法切换到WorkoutsPage:
// 假设1是WorkoutsPage在_pages里的索引 mainPageKey.currentState?.switchToPage(1);
这样操作后,底部导航栏会一直保留,因为你只是在父页面的body里切换子页面,没有替换整个路由。
思路二:调整路由结构,让底部导航作为父路由
如果一定要用Navigator跳转,那得让底部导航所在的页面始终作为根路由,WorkoutsPage作为它的子页面存在。可以给每个底部导航选项配一个独立的子导航器:
class MainPageState extends State<MainPage> { int _selectedIndex = 0; // 给每个页面配一个导航器key final List<GlobalKey<NavigatorState>> _navigatorKeys = [ GlobalKey<NavigatorState>(), GlobalKey<NavigatorState>(), ]; @override Widget build(BuildContext context) { return Scaffold( body: IndexedStack( index: _selectedIndex, children: [ // 首页的子导航器 Navigator( key: _navigatorKeys[0], onGenerateRoute: (settings) => MaterialPageRoute( builder: (context) => const HomeScreen(), ), ), // 训练页的子导航器 Navigator( key: _navigatorKeys[1], onGenerateRoute: (settings) => MaterialPageRoute( builder: (context) => const WorkoutsPage(), ), ), ], ), bottomNavigationBar: BottomNavigationBar( currentIndex: _selectedIndex, onTap: (index) => setState(() => _selectedIndex = index), items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'), BottomNavigationBarItem(icon: Icon(Icons.fitness_center), label: '训练'), ], ), ); } }
之后提交按钮跳转时,用训练页对应的子导航器:
_navigatorKeys[1].currentState?.pushReplacement(MaterialPageRoute( builder: (context) => const WorkoutsPage(), ));
这种方式下,底部导航栏始终在根Scaffold里,不会被替换掉。
内容的提问来源于stack exchange,提问作者A_K
相关产品推荐
相关产品推荐

