一、报错信息

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
====================================================================================================

【错误记录】Flutter 界面跳转报错 ( Navigator operation requested with a context that does not include a Naviga )_Flutter

错误代码 :

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://img-blog.csdnimg.cn/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://img-blog.csdnimg.cn/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(),
    )
  );
}