使用BottomNavigationBar与PageView时,跳转新页面如何保留底部导航栏?
方案1:将目标页面整合到PageView的页面集合中
把D页面直接加入PageView的页面列表,默认不在BottomNavigationBar显示入口,从A页面触发跳转时,直接切换PageView的索引到D对应的位置,底部导航栏会始终保持显示。
示例代码:
class MainPage extends StatefulWidget { @override _MainPageState createState() => _MainPageState(); } class _MainPageState extends State<MainPage> { int _currentIndex = 0; // 包含A、B、C、D四个页面 final List<Widget> _pages = [ APage(), BPage(), CPage(), DPage(), ]; // 切换到D页面的方法 void _navigateToD() { setState(() { _currentIndex = 3; }); } @override Widget build(BuildContext context) { return Scaffold( body: PageView( controller: PageController(initialPage: _currentIndex), onPageChanged: (index) { setState(() { _currentIndex = index; }); }, children: _pages, ), bottomNavigationBar: BottomNavigationBar( // 跳转到D时,底部导航保持选中A的位置 currentIndex: _currentIndex > 2 ? 0 : _currentIndex, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: 'A'), BottomNavigationBarItem(icon: Icon(Icons.business), label: 'B'), BottomNavigationBarItem(icon: Icon(Icons.school), label: 'C'), ], onTap: (index) { setState(() { _currentIndex = index; }); PageController().jumpToPage(index); }, ), ); } } // A页面中触发跳转 class APage extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: ElevatedButton( onPressed: () { // 调用父页面的切换方法 (context.findAncestorStateOfType<_MainPageState>())?._navigateToD(); }, child: Text('跳转到D页面'), ), ); } }
这种方式实现简单,复用现有PageView的切换逻辑,缺点是D页面会被预加载,需要在D页面添加返回逻辑(比如点击按钮切回A页面的索引)。
方案2:使用嵌套Navigator实现局部页面跳转
在A页面内部嵌套一个独立的Navigator,跳转到D页面时,仅在A页面的子导航栈中操作,外层的BottomNavigationBar不受任何影响,适合D页面有多层跳转需求的场景。
示例代码:
class MainPage extends StatefulWidget { @override _MainPageState createState() => _MainPageState(); } class _MainPageState extends State<MainPage> { int _currentIndex = 0; final List<Widget> _pages = [ APageWithNavigator(), // 带嵌套导航的A页面 BPage(), CPage(), ]; @override Widget build(BuildContext context) { return Scaffold( body: PageView( controller: PageController(initialPage: _currentIndex), onPageChanged: (index) { setState(() { _currentIndex = index; }); }, children: _pages, ), bottomNavigationBar: BottomNavigationBar( currentIndex: _currentIndex, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: 'A'), BottomNavigationBarItem(icon: Icon(Icons.business), label: 'B'), BottomNavigationBarItem(icon: Icon(Icons.school), label: 'C'), ], onTap: (index) { setState(() { _currentIndex = index; }); PageController().jumpToPage(index); }, ), ); } } // 嵌套Navigator的A页面容器 class APageWithNavigator extends StatelessWidget { static GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>(); @override Widget build(BuildContext context) { return Navigator( key: _navigatorKey, initialRoute: '/', onGenerateRoute: (settings) { switch (settings.name) { case '/': return MaterialPageRoute(builder: (_) => APage()); case '/d': return MaterialPageRoute(builder: (_) => DPage()); default: return null; } }, ); } } // A页面触发跳转 class APage extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: ElevatedButton( onPressed: () { Navigator.pushNamed(context, '/d'); }, child: Text('跳转到D页面'), ), ); } } // D页面 class DPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('D页面')), body: Center( child: ElevatedButton( onPressed: () { Navigator.pop(context); }, child: Text('返回A页面'), ), ), ); } }
这种方式更贴合常规页面跳转逻辑,每个子页面拥有独立的导航栈,外层BottomNavigationBar完全不受子页面跳转影响。
内容的提问来源于stack exchange,提问作者12341413451354134
相关产品推荐
相关产品推荐

