在上一篇我们已经讲了Flutter Navigation的基本使用,有兴趣或者对这一块还不太了解的同学可以去看看。在实际项目中我们可能会遇到一些比较特殊或者复杂的需求,而基本的跳转方式已经不能满足了,这一篇我们主要看一下Flutter的一些比较品如的跳转操作。

不得不说Flutter真的很良心,提供的一些跳转方式都非常实用,让我们日常的开发效率提升了很多,下面我们就一个一个的来介绍吧。

1.PushAndRemove

假设有这么一个场景:我们在开发一个商城项目,从选择商品到支付完成会经过主页面,商品列表页,商品详情页,支付页面,支付结果页。这时候来了一个需求,当跳转到支付结果页的时候将之前所有的页面都销毁,只留下主页面。如果是android可能会用到singletask或者自己写一个activity管理器之类的,但是这些实现方式都显得不那么优雅直接,而Flutter给出的跳转方案能完美地解决这类问题。

下面我们来看一下对于这类场景Flutter地解决方案

  1. 新建4个页面,Screen1,Screen2,Screen3,Screen4
  2. 在MaterialApp中添加这4个页面的路由
  3. 使用Navigator.of(context).pushAndRemoveUntil()或者Navigator.of(context).pushNamedAndRemoveUntil()进行跳转

1.1 新建页面

class Screen1 extends StatelessWidget {@overrideWidget build(BuildContext context) {return Container(alignment: Alignment.center,child: RaisedButton(onPressed: () {Navigator.pushNamed(context, '/screen2');},child: Text('screen1',style: TextStyle(fontSize: 30),),),);}
}

其它三个页面的样式和Screen1保持一致,点击按钮跳转到下一个页面

1.2 在MaterialApp中添加这4个页面的路由

@override
Widget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),routes: {'/screen1': (context) => Screen1(),'/screen2': (context) => Screen2(),'/screen3': (context) => Screen3(),'/screen4': (context) => Screen4(),},initialRoute: '/screen1',);
}

1.3 进行跳转操作

本例中我们的跳转顺序是Screen1—>Screen2—>Screen3—>Screen4

当从Screen3跳转到Screen4的时候我们希望将Screen2,Screen3从栈里面移除掉,这样在Screen4点击返回就能直接回到Screen1

使用Navigator.pushAndRemoveUtil()或者Navigator.pushNamedAndRemoveUntil()实现,这个方法有两个必传参数newRoute和predicate,第一个参数表示将要加入栈中的页面,第二个参数表示栈中要保留的页面底线,意思就是在predicate和newRoute之间的页面都会被移除栈

class Screen3 extends StatelessWidget {@overrideWidget build(BuildContext context) {return Container(alignment: Alignment.center,child: RaisedButton(onPressed: () {//跳转到screen4,并且移除所有的页面直到screen1
//          Navigator.of(context).pushNamedAndRemoveUntil(
//              '/screen4', ModalRoute.withName('/screen1'));Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => Screen4()),ModalRoute.withName('/screen1'));},child: Text('screen3',style: TextStyle(fontSize: 30),),),);}
}

2.pushReplacement

假设我们在做一个登录功能,在登录成功后需要跳转到一个新的页面并且销毁当前登录页,这时候就可以用pushReplacement来实现,从字面上的意思看push很好理解,把一个新页面压入栈中嘛,replacement到底是替代那个页面呢?答案是当前页,因为被替换的对象是固定的,所以该方法的必传参数只有被push的路由。

class Screen3 extends StatelessWidget {@overrideWidget build(BuildContext context) {return Container(alignment: Alignment.center,child: RaisedButton(onPressed: () {//打开Screen4页面,并销毁当前页Navigator.of(context).pushReplacementNamed('/screen4');//也可以使用以下方式//Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=>Screen3()));},child: Text('screen3',style: TextStyle(fontSize: 30),),),);}
}

3.popUntil

这个比较简单,从字面意思上就可以看出是“一直退出直到某一个页面”,来看一下用法吧

class Screen4 extends StatelessWidget {@overrideWidget build(BuildContext context) {return Container(alignment: Alignment.center,child: RaisedButton(onPressed: () {//当前在Screen4页面,点击回到Screen1,连带着Screen2,Screen3也一起退出Navigator.of(context).popUntil(ModalRoute.withName('/screen1'));},child: Text('screen4',style: TextStyle(fontSize: 30),),),);}
}

4.popAndPushNamed

这个方法和pushReplacement很相近,都是开启一个新的页面并且销毁之前的页面,只是在逻辑上的执行顺序不一样,popAndPushNamed是退出当前页面并且将新的页面放到它原来的位置上,所以在视觉效果上是先退出再进入

class Screen2 extends StatelessWidget {@overrideWidget build(BuildContext context) {return Container(alignment: Alignment.center,child: RaisedButton(onPressed: () {//点击退出当前页面,并将Screen3压入栈中Navigator.of(context).popAndPushNamed('/screen3');},child: Text('screen2',style: TextStyle(fontSize: 30),),),);}
}

仔细看动图,Screen2到Screen3的时候是先将Screen2退出再显示Screen3,它不像pushReplacement那样无感知的就把页面给替换了。所以大家根据实际场景选择使用。

备注:以上所有的方法都可以传递相应的参数,涉及到pop的可以加入返回参数,涉及到push的可以添加传递到新页面的参数,这里没有做过多的赘述,大家可以自己尝试一下。

5.maybePop和canPop

Navigator.of(context).canPop()返回一个bool值,表示当前页面是否可以退出,那么判断的依据是啥呢?追溯到源码去看
/// Whether the navigator can be popped.////// {@macro flutter.widgets.navigator.canPop}////// See also://////  * [Route.isFirst], which returns true for routes for which [canPop]///    returns false.bool canPop() {assert(_history.isNotEmpty);return _history.length > 1 || _history[0].willHandlePopInternally;}

尤其是这句话哦: [Route.isFirst], which returns true for routes for which [canPop],意思说的很明显了,判断依据就是看当前路由是否处在栈中“最底部”的位置。根据之前的例子,如果我们在Screen1调用canPop肯定返回false,因为它处在“最底部”的位置,而在其它页面调用则返回true

Navigator.of(context).maybePop()是一种很友善的退出方式,如果能退出就退出,不退出拉到。其实这个方法可以理解为

maybePop() => canPop() == true?pop() : do nothing

所以在首页调用maybePop()是不会退出的,如果在其它页面调用,效果和pop()一样

关于Navigator的push,pop使用姿势就这么多了,不正确的地方欢迎大家指正!

Flutter Navigator 高级用法相关推荐

  1. vim的高级用法配置以及在系统中如何获取帮助

    vim的高级用法配置以及在系统中如何获取帮助 1 vim的三种模式 1.1 使用方法 1.2 vim模式 2 vim工作的基本配置 2.1 临时设定(set设定) 2.2 永久设定方式 3 搜索 4 ...

  2. Cacti Weathermap 高级用法 (二)

    成都长宽Weathermap实际运用的效果图示例: 这是一个CNC出口的质量监控图. 途中cnc节点(红色)是一个展示图例,TEL节点根据存活状态显示为绿色 TEL节点上面P:47.2ms 是一个,这 ...

  3. JAVA正则表达式高级用法(分组与捕获)

    2019独角兽企业重金招聘Python工程师标准>>> 正则表达式在字符串处理中经常使用,关于正则简单的用法相信有一点程序基础的人都懂得一些,这里就不介绍简单基础了.这里主要讲解一下 ...

  4. GUN sed高级用法,sed脚本编写

    这里举一些sed常用的高级用法例子经供参考: 一下操作都针对file.txt文件作修改 [root@QX-××× ~]# cat file.txt libgcc-4.4.7-4.el6.x86_64 ...

  5. java return用法_Java枚举的高级用法之多键值的映射使用

    枚举Enum单映射使用 做Java的各位仁兄姐妹都知道,Java通过HashMap,以及枚举提供了方便的K-V映射功能,例如 枚举单映射使用 但是如果遇到多个键值映射,例如K-K-V的形式怎么办呢?可 ...

  6. (转)python requests 高级用法 -- 包括SSL 证书错误的解决方案

    (转)python requests 高级用法 -- 包括SSL 证书错误的解决方案 参考文章: (1)(转)python requests 高级用法 -- 包括SSL 证书错误的解决方案 (2)ht ...

  7. Python 内置函数sorted()在高级用法

    对于Python内置函数sorted(),先拿来跟list(列表)中的成员函数list.sort()进行下对比.在本质上,list的排序和内建函数sorted的排序是差不多的,连参数都基本上是一样的. ...

  8. class() 高级用法 -- lua

    class() 高级用法 class() 除了定义纯 Lua 类之外,还可以从 C++ 对象继承类.比如需要创建一个工具栏,并在添加按钮时自动排列已有的按钮,那么我们可以使用如下的代码:-- 从 CC ...

  9. Newtonsoft.Json高级用法

    手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数 ...

  10. Python进阶:切片的误区与高级用法

    众所周知,我们可以通过索引值(或称下标)来查找序列类型(如字符串.列表.元组...)中的单个元素,那么,如果要获取一个索引区间的元素该怎么办呢? 切片(slice)就是一种截取索引片段的技术,借助切片 ...

最新文章

  1. 教程 | OpenCV4中的极坐标变换
  2. oracle 之 EXP、IMP 使用简介
  3. java jar 版本号_java – 获取JAR文件版本号
  4. poj2112(网络流-最大流+二分)
  5. unicone 字体 规范
  6. Java中 读-写 文件 BufferedReader BufferedWriter
  7. SQL 性能优化梳理 —— 基本概念、创建时优化、查询时优化
  8. Python快速定位工作目录
  9. python tvtk库_PyCharm创建虚拟环境 和 TVTK库的安装
  10. 玩转Redis集群(下)
  11. 最全的BAT Google等团队技术博客集合
  12. 第二课--C语言基础(1,2部分--共三部分)
  13. python怎么读中文-python读取中文txt文本的方法
  14. php hidden属性,微信小程序关于组件的hidden属性的使用建议
  15. MPPT “最大功率点跟踪”
  16. 【每天play】为了学好python需要从脚下做起,Linux基础-用户权限与组管理 P60-70
  17. 置换的玩笑——DFS暴力
  18. C#语言跟WPF学习视频
  19. pycharm创建django项目及开发初准备
  20. 你知道外卖cps是什么吗?(附裂变分销小程序源码搭建教程)

热门文章

  1. EasyCVR通过GB28181级联到紫光华智综合安防应用平台无法注册成功问题排查
  2. java实现京东登陆界面_京东登陆界面的实现
  3. fnv1 java_笔记本热键驱动_笔记本万能fn键驱动 v1.1 通用版-126g驱动网
  4. c语言 申请变量函数,C语言中变量和函数
  5. uni-app实现实时获取当前时间日期
  6. Autovue 集成
  7. tiny-emitter.js:一个小型的事件订阅发布库
  8. 计算机无法上无线网络连接到internet,电脑连接不上无线网络,教您怎么解决电脑连接不上无线网络...
  9. 序:我的多旋翼飞控学习之路
  10. 【无机纳米材料科研制图——OriginLab 0209】Origin散点图线性拟合与非线性拟合