热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

代码跳转路由报错_flutter路由

路由管理控制路由是一个应用程序抽象的屏幕或页面;路由管理就是管理页面之间如何跳转;路由入栈指打开一个新页面;路由出栈指一个页面关闭操作&#

路由管理控制

  • 路由是一个应用程序抽象的屏幕或页面;
  • 路由管理就是管理页面之间如何跳转;
  • 路由入栈指打开一个新页面;
  • 路由出栈指一个页面关闭操作;
  • 路由管理指如何来管理路由栈;
  • Navigator是一个管理路由的widget;
  • NavigatorKey是一个管理路由的Key;

看完本文你将学会路由的使用管理好一个路由路由传参路由带参返回路由记录返回到指定路由路由动画, 然后使用pop操作来进行回退到某个路由;

Navigator

方法作用

开始上手

我们创建个普通路由跳转,跳转到原页面,但是标题的数量会+1,让我们知道当前是push到的第几个页面;

路由跳转传参示例:

import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return new MaterialApp(title: 'Flutter高级进阶',home: new MyHomePage(),);}
}class MyHomePage extends StatefulWidget {// 接收的num参数final int num;// MyHomePage不写参数则默认为1MyHomePage({this.num = 1});@override_MyHomePageState createState() => _MyHomePageState();
}class _MyHomePageState extends State {@overrideWidget build(BuildContext context) {return new Scaffold(// 显示接收的num参数appBar: new AppBar(title: new Text('Flutter高级进阶${widget.num}')),// 按钮点击执行跳转方法body: new FlatButton(child: new Text("push"), onPressed: () => push()),);}/** 路由跳转方法* */push() {// 拿到传过来的num然后+1 int num = widget.num + 1;//导航到新路由Navigator.push(context,MaterialPageRoute(// num传给下一级builder: (context) => MyHomePage(num: num)),);}
}

效果图:

bad15ead8ccd71dd2b374567a97fa504.gif

错误示例:

class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return new MaterialApp(title: 'Flutter高级进阶',home: new Scaffold(appBar: new AppBar(),body: new FlatButton(child: new Text("push"), onPressed: () => push(context)),),);}/** 路由跳转方法* */push(context) {//导航到新路由Navigator.push(context,MaterialPageRoute(// MyHomePage不写参数则默认为1builder: (context) => MyHomePage()),);}
}

报错信息:

I/flutter (21935): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
I/flutter (21935): The following assertion was thrown while handling a gesture:
I/flutter (21935): Navigator operation requested with a context that does not include a Navigator.
I/flutter (21935): The context used to push or pop routes from the Navigator must be that of a widget that is a
I/flutter (21935): descendant of a Navigator widget.
I/flutter (21935):
I/flutter (21935): When the exception was thrown, this was the stack:
I/flutter (21935): #0 Navigator.of. (package:flutter/src/widgets/navigator.dart:1475:9)
I/flutter (21935): #1 Navigator.of (package:flutter/src/widgets/navigator.dart:1482:6)
I/flutter (21935): #2 Navigator.push (package:flutter/src/widgets/navigator.dart:1107:22)
I/flutter (21935): #3 MyApp.push (package:oc_project/main.dart:18:15)
I/flutter (21935): #4 MyApp.build. (package:oc_project/main.dart:12:72)
I/flutter (21935): #5 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:654:14)
I/flutter (21935): #6 _InkResponseState.build. (package:flutter/src/material/ink_well.dart:729:32)
I/flutter (21935): #7 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
I/flutter (21935): #8 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:365:11)
I/flutter (21935): #9 TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:275:7)
I/flutter (21935): #10 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:455:9)
I/flutter (21935): #11 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:75:13)
I/flutter (21935): #12 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:102:11)
I/flutter (21935): #13 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:218:19)
I/flutter (21935): #14 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22)
I/flutter (21935): #15 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
I/flutter (21935): #16 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)
I/flutter (21935): #17 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)
I/flutter (21935): #21 _invoke1 (dart:ui/hooks.dart:263:10)
I/flutter (21935): #22 _dispatchPointerDataPacket (dart:ui/hooks.dart:172:5)
I/flutter (21935): (elided 3 frames from package dart:async)
I/flutter (21935):
I/flutter (21935): Handler: "onTap"
I/flutter (21935): Recognizer:
I/flutter (21935): TapGestureRecognizer#72729

这个报错是因为用的这个上下文是MaterialApp的,这个上下文不包含Navigator导航器操作, 所以我们应该把home的那部分抽出来放另一个类;

路由传值并返回值

路由传参在上面那个例子已经有了,num就是我们的参数,然后显示在标题上就是使用了。

这节教大家路由传值并返回值,创建个NewPage,接收个文本值text,然后显示在新页面,新页面给个返回按钮, 点击返回按钮返回并带回一串值回去。

NewPage:

class NewPage extends StatelessWidget {final String text;NewPage({@required this.text, // 接收一个text参数});@overrideWidget build(BuildContext context) {return new Scaffold(appBar: new AppBar(title: new Text("新页面:$text")),body: new RaisedButton(onPressed: () => Navigator.pop(context, "我是返回值"),child: new Text("返回"),),);}
}

然后之前写好的push方法改下,用then接收:

/** 路由跳转方法* */
push() {//导航到新路由Navigator.push(context,MaterialPageRoute(// 拿到传过来的num然后++传给下一级builder: (context) => NewPage(text: '参数'),),).then((value) {if (value != null) print('接收到的参数:$value');});
}

这样我们就能push到新页面然后点击返回按钮就能把参数返回到push到它的那个方法,然后在then打印出来了:

I/flutter (21935): 接收到的参数:我是返回值

直接点击左上角那个返回值会为空,这样打印出来的就是:

I/flutter (21935): 接收到的参数:null

所以我们做了一个判断,不为空才执行打印,如果为空就不做任何操作;

路由命名

我们想执行跟name有关的Navigator方法就必须先给路由命名,比如pushNamed方法, 注册路由在MaterialApproutes属性,它的定义为:

final Map routes;

注册示例

class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return new MaterialApp(title: 'Flutter高级进阶',routes: {"newPage": (context) => new NewPage(text: '注册路由名的新页面'),},home: new MyHomePage(),);}
}

这样我们的newPage就注册好了,然后试试pushNamed方法:

/** 路由跳转方法* */
push() {Navigator.pushNamed(context, "newPage").then((value) {if (value != null) print('接收到的参数:$value');});
}

效果图:

14d17584b5c4de984a791d8b163e50d2.gif

返回到指定路由

这节我们使用popUntil方法返回到我们想要返回到的某个路由,首先再注册两个路由名:

@override
Widget build(BuildContext context) {return new MaterialApp(title: 'Flutter高级进阶',routes: {// 新页面路由名"newPage": (context) => new NewPage(text: '注册路由名的新页面'),// 第二个路由名"towPage": (context) => new TowPage(),// 首页路由名"/": (context) => new MyHomePage(),},
// home: new MyHomePage(), 这个必须注释,因为我们注册了根路由名:"/",否则报错);
}

TowPage:

class TowPage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: new AppBar(title: new Text('页面二')),body: new RaisedButton(onPressed: () => Navigator.popUntil(context, ModalRoute.withName('/')),child: new Text("返回到首页"),),);}
}

然后NewPage把返回改成push到第二个页面:

class NewPage extends StatelessWidget {final String text;NewPage({@required this.text, // 接收一个text参数});@overrideWidget build(BuildContext context) {return new Scaffold(appBar: new AppBar(title: new Text("新页面:$text")),body: new RaisedButton(onPressed: () => Navigator.pushNamed(context, "towPage"),child: new Text("到第二个页面"),),);}
}

效果图:

1a337c7acd8d860cac92b2a154cd1ff7.gif

这样就实现了到第二个页面的时候点击回到首页按钮就直接返回到首页了。

路由记录

我们每次跳转一个新路由然后想返回到之前跳转过的某个路由难道每个都要注册路由名吗?那样的话太麻烦了, 这节就教大家路由记录,只要我们跳转过某个路由就记录起来, 然后最后面的路由想返回到前面的三个中的某个都不需要配置名字了。

配置:

/** 路由跳转方法* */
push() {Navigator.push(context,MaterialPageRoute(builder: (context) => MyHomePage(),settings: new RouteSettings(name: MyHomePage().toStringShort(), // 设置的路由名isInitialRoute: false, // 是否初始路由),),);
}

这样我们就把我们要跳转到的MyHomePage跳转了,同时还记录了路由名字;

使用:

class TowPage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: new AppBar(title: new Text('页面二')),body: new RaisedButton(onPressed: () => Navigator.popUntil(context,// 使用记录好的路由名字ModalRoute.withName(MyHomePage().toStringShort()),),child: new Text("返回到MyHomePage"),),);}
}

这样我们就可以完美的返回到MyHomePage页面了,使用起来非常方便。

路由动画理论

路由动画就是我们跳转到下一个路由栈的时候所产生的过度动画,官方提供了两个动画: MaterialPageRouteCupertinoPageRoute;

解释:

  • MaterialPageRoute:存在于:import 'package:flutter/material.dart';包;
  • CupertinoPageRoute:存在于:import 'package:flutter/cupertino.dart';包;

使用:

直接把我们用来push的MaterialPageRoute更改为:CupertinoPageRoute即可查看动画效果;

自定义路由动画

首先编写好一个路由动画,路由动画必须继承至PageRouteBuilder:

/*
* 渐变动画
* */
class FadeRoute extends PageRouteBuilder {// 传过来的页面pagefinal Widget page;// 构造FadeRoute({this.page}): super(pageBuilder: (BuildContext context,Animation animation,Animation secondaryAnimation,) =>page,transitionsBuilder: (BuildContext context,Animation animation,Animation secondaryAnimation,Widget child,) =>FadeTransition(opacity: animation, // 透明度child: child, // 页面存放),);
}

然后push方法直接更改为:

push() {Navigator.push(context,FadeRoute(page: MyHomePage()),);
}




推荐阅读
  • C++ STL复习(13)容器适配器
    STL提供了3种容器适配器,分别为stack栈适配器、queue队列适配器以及priority_queue优先权队列适配器。不同场景下,由于不同的序列式 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • 本文介绍了一道经典的状态压缩题目——关灯问题2,并提供了解决该问题的算法思路。通过使用二进制表示灯的状态,并枚举所有可能的状态,可以求解出最少按按钮的次数,从而将所有灯关掉。本文还对状压和位运算进行了解释,并指出了该方法的适用性和局限性。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 本文主要介绍了gym102222KVertex Covers(高维前缀和,meet in the middle)相关的知识,包括题意、思路和解题代码。题目给定一张n点m边的图,点带点权,定义点覆盖的权值为点权之积,要求所有点覆盖的权值之和膜qn小于等于36。文章详细介绍了解题思路,通过将图分成两个点数接近的点集L和R,并分别枚举子集S和T,判断S和T能否覆盖所有内部的边。文章还提到了使用位运算加速判断覆盖和推导T'的方法。最后给出了解题的代码。 ... [详细]
  • Flutter 布局(四) Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth详解
    本文主要介绍Flutter布局中的Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth四种控件,详细介绍了其布局 ... [详细]
  • 第一步:PyQt4Designer设计程序界面该部分设计类同VisvalStudio内的设计,改下各部件的objectName!设计 ... [详细]
  • [翻译]PyCairo指南裁剪和masking
    裁剪和masking在PyCairo指南的这个部分,我么将讨论裁剪和masking操作。裁剪裁剪就是将图形的绘制限定在一定的区域内。这样做有一些效率的因素࿰ ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
author-avatar
为什么要这2502928433
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有