文章目录
一、报错信息
二、问题分析
三、解决方案
一、报错信息
Flutter 界面跳转时 , 报如下错误 :
======== Exception caught by gesture =============================================================== The following assertion was thrown while handling a gesture: Navigator operation requested with a context that does not include a Navigator. The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget. When the exception was thrown, this was the stack: #0 Navigator.of.<anonymous closure> (package:flutter/src/widgets/navigator.dart:2711:9) #1 Navigator.of (package:flutter/src/widgets/navigator.dart:2718:6) #2 HeroAnimation.build.<anonymous closure> (package:flutter_animation/main.dart:57:25) #3 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:994:20) #4 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24) ... Handler: "onTap" Recognizer: TapGestureRecognizer#68181 debugOwner: GestureDetector state: possible won arena finalPosition: Offset(216.4, 420.6) finalLocalPosition: Offset(160.7, 193.9) button: 1 sent tap down ====================================================================================================
错误代码 :
void main() { runApp( HeroAnimation() ); } class HeroAnimation extends StatelessWidget{ @override Widget build(BuildContext context) { // 时间膨胀系数 , 用于降低动画运行速度 timeDilation = 10.0; return MaterialApp( home: Scaffold( body: Container( child: HeroWidget( imageUrl: "https://ucc.alicdn.com/images/user-upload-01/20210329101628636.jpg", width: 300, // 点击事件 , 这里点击该组件后 , 跳转到新页面 onTap: (){ print("点击事件触发"); Navigator.of(context).push( MaterialPageRoute( builder: (context){ /// 跳转到的新界面再此处定义 return MaterialApp( home: Scaffold( body: Container( color: Colors.white, padding: EdgeInsets.all(20), alignment: Alignment.topLeft, child: HeroWidget( imageUrl: "https://ucc.alicdn.com/images/user-upload-01/20210329101628636.jpg", width: 100, onTap: (){ /// 退出当前界面 Navigator.of(context).pop(); }, ), ), ), ); } ) ); }, ), ), ), ); } }
二、问题分析
Navigator operation requested with a context that does not include a Navigator.
该错误与跳转的目标界面无关 , 只与当前的界面有关 ;
The [MaterialApp] configures the top-level [Navigator] to search for routes in the following order: 1. For the `/` route, the [home] property, if non-null, is used. 2. Otherwise, the [routes] table is used, if it has an entry for the route. 3. Otherwise, [onGenerateRoute] is called, if provided. It should return a non-null value for any _valid_ route not handled by [home] and [routes]. 4. Finally if all else fails [onUnknownRoute] is called. If a [Navigator] is created, at least one of these options must handle the `/` route, since it is used when an invalid [initialRoute] is specified on startup (e.g. by another application launching this one with an intent on Android; see [dart:ui.PlatformDispatcher.defaultRouteName]). This widget also configures the observer of the top-level [Navigator] (if any) to perform [Hero] animations. If [home], [routes], [onGenerateRoute], and [onUnknownRoute] are all null, and [builder] is not null, then no [Navigator] is created.
上面是 MaterialApp 的注释 , MaterialApp 中会自动创建一个 Navigator , 此处使用了 MaterialApp 仍然报上述错误 ;
Navigator 查找机制 : 这是由于调用了 Navigator.of(context) 代码获取 Navigator , 注意这里的 context 上下文关联的是 StatelessWidget 组件 , 也就是数从该 StatelessWidget 组件开始 , 向上查找 Navigator ;
但是实际的层级是这样的 , StatelessWidget 包裹 MaterialApp 包裹 Scaffold 包裹 Container , 查找 Navigator 时 , 越过了 MaterialApp , 直接从最顶层的 StatelessWidget 组件开始向上查找 , 肯定找不到 Navigator , 这里直接报错了 ;
这是由于 Navigator 的查找机制导致的错误 , 解决这个问题也很简单 , 在 StatelessWidget 的外层再包裹一个 MaterialApp , 这样就可以解决问题了 ;
三、解决方案
在 main.dart 中的 main() 函数中 , 使用 MaterialApp 包裹界面跳转的组件 ;
这样在 StatelessWidget 组件的外层又包裹了一层 MaterialApp , 这样从 StatelessWidget 组件开始向上查找 Navigator , 就可以找到 Navigator , 问题解决 ;
void main() { runApp( MaterialApp( title: "Hero 动画", home: HeroAnimation(), ) ); }