Flutter中从无底部导航栏页面返回底部导航栏的问题
问题描述
我在Flutter项目里用Google Nav Bar做底部导航栏,切换导航栏内的页面都正常。但从导航栏的Drawer页面跳转到无底部导航栏的Profile这类页面后,用Navigator.pop返回会出现路由错误,试了pushNamed也没解决。附上底部导航栏和ModalDrawer的代码,还有问题截图,求解决办法。
底部导航栏代码
import 'package:google_nav_bar/google_nav_bar.dart'; import 'package:flutter/material.dart'; import '../../Screens/screens_export.dart'; class GoogleNavBar extends StatefulWidget { const GoogleNavBar({Key? key}) : super(key: key); @override State<GoogleNavBar> createState() => _GoogleNavBarState(); } class _GoogleNavBarState extends State<GoogleNavBar> { int currentIndex = 2; final Screens = [ nderChat(), TBD(), Reports(), Drawer(), ]; @override Widget build(BuildContext context) { return Scaffold( body: Screens[currentIndex], bottomNavigationBar: Container( color: Colors.black, child: Padding( padding: const EdgeInsets.symmetric( horizontal: 15, vertical: 20), child: GNav( backgroundColor: Colors.black, color: Colors.white, activeColor: Colors.white, tabBackgroundColor: Colors.grey.shade800, padding: EdgeInsets.all(16), gap: 8, onTabChange: (index) => setState(() => currentIndex = index), tabs: const[ GButton( icon: Icons.groups_outlined, text: 'Global', ), GButton( icon: Icons.rss_feed_outlined, text: 'TBD', ), GButton( icon: Icons.running_with_errors_rounded, text: 'Alerts', ), GButton( icon: Icons.account_circle_outlined, text: 'Profile', ), ] ), ), ), ); } }
ModalDrawer代码
class ModalDrawer extends StatelessWidget { const ModalDrawer({Key? key}) : super(key: key); @override Widget build(BuildContext context) { double drawerWidth = MediaQuery.of(context).size.width; return Drawer( width: drawerWidth, backgroundColor: Colors.lightBlue, child: ListView( padding: const EdgeInsets.all(0), children: [ const DrawerHeader( decoration: BoxDecoration( color: Colors.blueGrey, ), child: UserAccountsDrawerHeader( decoration: BoxDecoration(color: Colors.blue), accountName: Text( "Alpha", style: TextStyle(fontSize: 18), ), accountEmail: Text("alpha@alphamail.com"), currentAccountPictureSize: Size.square(50), currentAccountPicture: CircleAvatar( backgroundColor: Colors.blue, child: Text( "A", style: TextStyle( fontSize: 30.0, color: Color.fromARGB(255, 255, 255, 255)), ), ), ), ), buildMenuItem( text: AppLocalizations.of(context)!.home, icon: Icons.home_outlined, onClicked: () => selectedItem(context, 0), ), buildMenuItem( text: AppLocalizations.of(context)!.profile, icon: Icons.person_outline, onClicked: () => selectedItem(context, 1), ), buildMenuItem( text: AppLocalizations.of(context)!.faq, icon: Icons.question_mark_outlined, onClicked: () => selectedItem(context, 2), ), buildMenuItem( text: AppLocalizations.of(context)!.settings, icon: Icons.settings, onClicked: () => selectedItem(context, 3), ), buildMenuItem( text: 'chat', icon: Icons.message_outlined, onClicked: () => { showDialog(context: context, builder: (context) => SimpleDialogBox()), selectedItem(context, 4),}, ), ], ), ); } Widget buildMenuItem({ required String text, required IconData icon, required onClicked, }) { const colorImage = Color.fromARGB(255, 3, 3, 3); const colorText = Color.fromARGB(255, 0, 0, 0); return Padding( padding: const EdgeInsets.only(bottom: 1), child: ListTile( leading: Icon(icon, color: colorImage), title: Text(text, style: const TextStyle(color: colorText)), onTap: onClicked, ), ); } void selectedItem(BuildContext context, int index) { Navigator.of(context).pop(); switch (index) { case 0: Navigator.pushNamed(context, '/home'); break; case 1: Navigator.pushNamed(context, '/user'); break; case 2: Navigator.pushNamed(context, '/faq'); break; case 3: Navigator.pushNamed(context, '/settings'); break; case 4: Navigator.pushNamed(context, '/chatscreen'); break; } } }
问题截图说明
- 截图1:Profile导航项界面
- 截图2:无底部导航栏的Profile页面
- 截图3:点击App Bar左上角返回按钮后的报错界面
解决办法
问题根源
- 你把
ModalDrawer直接作为GoogleNavBar的一个页面成员(Screens数组里的Drawer()),导致Drawer嵌套在GoogleNavBar的Scaffold中,不是独立路由。从Drawer跳转后返回,会试图回到这个嵌套的Drawer页面,引发路由错误。 selectedItem方法中先关闭Drawer再pushNamed,如果目标路由已在栈中,会重复入栈,导致返回时栈结构混乱。
修复步骤
1. 调整GoogleNavBar的页面结构
把Screens里的Drawer()替换成带Drawer按钮的主页面(比如HomeScreen),让Drawer属于主页面的Scaffold,而非底部导航的一个页面:
final Screens = [ nderChat(), TBD(), Reports(), HomeScreen(), // 替换原Drawer() ];
HomeScreen示例代码:
class HomeScreen extends StatelessWidget { const HomeScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: Builder( builder: (context) => IconButton( icon: const Icon(Icons.menu), onPressed: () => Scaffold.of(context).openDrawer(), ), ), ), drawer: const ModalDrawer(), body: const Center(child: Text("主页面")), ); } }
2. 优化路由跳转逻辑
- 如果跳转到无底部导航的页面(如Profile),直接用
pushNamed即可,返回时会自动回到之前的底部导航页。 - 如果需要替换当前栈顶路由(比如从Drawer返回主页时避免重复入栈),改用
pushReplacementNamed:
void selectedItem(BuildContext context, int index) { Navigator.of(context).pop(); switch (index) { case 0: Navigator.pushReplacementNamed(context, '/home'); break; case 1: Navigator.pushNamed(context, '/user'); break; case 2: Navigator.pushNamed(context, '/faq'); break; case 3: Navigator.pushNamed(context, '/settings'); break; case 4: Navigator.pushNamed(context, '/chatscreen'); break; } }
3. 确保路由表配置正确
在MaterialApp的routes中正确配置所有页面路由,示例:
MaterialApp( routes: { '/': (context) => const GoogleNavBar(), '/home': (context) => const GoogleNavBar(), '/user': (context) => const UserProfileScreen(), // 无底部导航的Profile页面 '/faq': (context) => const FaqScreen(), '/settings': (context) => const SettingsScreen(), '/chatscreen': (context) => const ChatScreen(), }, )
4. 独立无底部导航的页面
确保Profile这类页面是独立的Scaffold,不嵌套在GoogleNavBar的Scaffold中:
class UserProfileScreen extends StatelessWidget { const UserProfileScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("个人中心")), body: const Center(child: Text("Profile页面")), ); } }
调整后路由结构清晰,返回时就不会出现错误了。
内容的提问来源于stack exchange,提问作者alphacruze
相关产品推荐
相关产品推荐

