使用pushNamed时设置rootNavigator: true引发Flutter路由异常
核心问题
你用rootNavigator: true调用pushNamed时,是让最外层的根Navigator处理路由跳转,但你的onGenerateRoute路由配置是写在首页里的嵌套Navigator(承载BottomNavBar页面切换的那个Navigator)中的。根Navigator完全不知道/comments这个路由的存在,所以才会抛出找不到路由生成器的错误。
而之前用Navigator.of(context, rootNavigator: true).push()能成功,是因为push()直接传入了页面的Route对象,不需要依赖路由生成器,根Navigator可以直接处理;但pushNamed必须要求处理它的Navigator(这里是根Navigator)提前配置好对应路由的生成规则。
解决方法
方法一:把全局路由配置移到根Navigator(推荐)
把所有需要全局跳转的路由配置直接写在MaterialApp(或CupertinoApp)里,让根Navigator管理所有命名路由:
MaterialApp( initialRoute: '/home', // 用onGenerateRoute统一管理路由 onGenerateRoute: (settings) { switch (settings.name) { case '/home': // 首页包含BottomNavBar和嵌套Navigator return MaterialPageRoute(builder: (_) => HomePageWithBottomNavBar()); case '/comments': // 第二页,跳转后会覆盖BottomNavBar return MaterialPageRoute(builder: (_) => SecondPage()); default: return MaterialPageRoute(builder: (_) => NotFoundPage()); } }, )
然后在首页的嵌套Navigator里,只处理BottomNavBar对应的页面切换(比如首页的几个tab页),不需要配置全局路由。跳转第二页时,直接用:
Navigator.of(context, rootNavigator: true).pushNamed('/comments');
这样根Navigator能识别/comments路由,跳转后自然会覆盖BottomNavBar。
方法二:给嵌套Navigator设置全局key(不推荐,仅特殊场景用)
如果不想把路由都放根Navigator,可以给首页的嵌套Navigator设置一个GlobalKey<NavigatorState>,然后通过这个key获取嵌套Navigator的上下文来跳转,但这种方式跳转后还是会显示BottomNavBar,不符合你的需求,所以更推荐方法一。
额外检查点
- 确认
MaterialApp的routes或onGenerateRoute里确实包含了/comments的路由定义,不要只在嵌套Navigator里配置。 - 跳转时的路由名称要和配置的完全一致(比如大小写、斜杠不要错)。
内容的提问来源于stack exchange,提问作者bryhaw

