Flutter开发 -- 导航

省流:官网也在强推go_router,各位看官可以跳到使用路由那块直接看。

导航对于任何应用程序都非常重要。它为各种平台提供的导航 API 提供了统一的抽象。Flutter 为导航提供了两种类型的 API:命令式和声明式。## 命令式导航最常用的一种导航的方式,也是最简单的一种。命令式导航由一个栈的Widget组成,通过push压栈,通过pop从栈里弹出。push方法让你导航的一个新的页面,而pop则从当前页面返回到上一个页面。我们来看一个简单的例子:
注意push之后就会跳转到DetailScreen了。

在DetailScreen调用pop可以返回:

Navigator类提供了导航需要的所有功能。同时,还提供了一个pushReplaceent的方法。这个方法和push类似,但是会把当前路由删除,也就是说导航到新的页面之后再导航回来是不可能的。这个场景正好适合登录,登录成功之后用户无法回退到登录页面。

命名导航

使用命名导航,你可以只用字符串就切换不同的页面。这主要是通过定义一个路由字典实现的。

定义路由

路由的定义由字符串为Key,页面实例为值的字典组成。然后传入到MaterialApp的routes属性:

在我们的todo app里面的修改可以是这样的:

随后就要修改HomeScreen跳转的方法:注释掉的就是我们之前用的导航代码。现在使用了Navigator.pushNamed这个方法,然后传入定义好的路由的名称detail就可以跳转到详细页面了。

传递数据

在导航中传递参数

就如上例中我们提到的,从todo 列表页跳转到详细页的时候还显示的是一个可以回退的按钮。这是我们为了显示导航的功能而做的。但是这是不够的。在跳转到详细页的时候本来应该展示的是todo的详情内容。这就需要导航到新的页面的时候还要把数据也一起传递过去。另外还要介绍一个情况就是,从新的路由里返回数据。

最简单的一种方法是在push的时候,初始化DetailScreen的时候给他传入一个参数,也就是给DetailScreen添加一个构造函数参数。这里就不细说了。

真正的参数是这样传递的:

在push的时候,在MaterialPageRoute里给settings值。然后,在DetailScreen中把参数读取出来:final todo = ModalRoute.of(context)!.settings.arguments as TodoItem;就是用来读取导航传递的参数的。


在导航中返回数据

现在来实现返回数据的功能。比如,如果一个用户查看了todo的内容,那么就返回以后弹出一个"已读"的snackbar。就像这样:

首先修改HomeScreen的代码:

主要看第二行,给push的方法加一个await,然后读取一个返回值给result赋值。得到值之后显示一个snackbar说明todo详情已读。

之后修改DetailScreen页面。需要改的地方不多,只要改pop加一个需要返回的值作为参数。像这样:Navigator.pop(context, '${todo.content} is read');。

以上都是在命令导航中传递参数的方法。先在看看如何在命名导航中传递参数。

首先,需要在MaterialApp中配置routes属性。这个前文已经讲过了。然后在pushNamed加上要传递的参数。

然后在DetailScreen里读取参数。还是老方法:

在新一版本的Flutter中,引入了基于Page的导航。这些在第三方库中广泛使用,比如go_router。有兴趣的可以了解一下。

注意:Flutter不推荐使用命名导航的方式。主要是因为命名路由在支持deep link和flutter web的时候有问题

使用路由

这是一个声明式的方式定义路由的方法。在前面讲到的内容中,如果要同时push或者pop多个页面,或者对当前页面以外的路由操作都不是很容易。Router,我们要讲的,可以非常容易的处理以上的问题。

具体基于pages的路由可以参考官网。在后续的deep link的讲解中会用到go_router。所以,我们这里着重讲解一下这个库的一些常用方法。

首先下载go_router包。

然后去掉之前的所有路由的代码,添加基于go_router的代码:

修改的时候,只需要把之前的MaterialApp改成MaterialApp.router。其他的不用改,之后把routes改成routerConfig。

routerConfig添加一些路由: "/"这个路由对应的就是HomeScreen,"/detail"对应的就是DetailScreen页面。"/settings"对应的就是SettingsScreen。

在settings这个路由下还有一个子路由:"isolate"。这是go_router的子路由。

在导航到下一个页面的时候可以使用context.push(目标路由)的方式也可以使用context.go(目标路由)的方式。二者路由有区别。使用go的方式,之前的路由历史会被清理出路由栈。在使用的时候需要注意!

使用push跳转到设置页:

使用go跳转到isolate页面:

就是这么简单!

使用go_router的情况下,如何传递参数呢?也很简单。

路径参数(path params)

查询参数(query params)

在导航的时候可以这样:

附加参数(extra params)

导航的时候:

带值pop

使用go_router一样可以实现pop回来同时传递参数的效果:在HomeScreen里导航到DetailScreen。这个额外需要做的就是要在push的时候await。同时接收返回的结果。

在得到结果之后显示一个snackbar。

在DetailScreen里,pop回来的时候context.pop(widget.todo.content);。pop回来的时候到这一个参数,它的值是跳转过去的todo的内容。

运行起来看看吧!

相关推荐
服装学院的IT男4 小时前
【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-2
android
Arms2064 小时前
android 全面屏最底部栏沉浸式
android
服装学院的IT男4 小时前
【Android 源码分析】Activity生命周期之onStop-1
android
ChinaDragonDreamer6 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
网络研究院9 小时前
Android 安卓内存安全漏洞数量大幅下降的原因
android·安全·编程·安卓·内存·漏洞·技术
凉亭下9 小时前
android navigation 用法详细使用
android
早起的年轻人11 小时前
Flutter String 按 ,。分割
flutter
小比卡丘11 小时前
C语言进阶版第17课—自定义类型:联合和枚举
android·java·c语言
前行的小黑炭12 小时前
一篇搞定Android 实现扫码支付:如何对接海外的第三方支付;项目中的真实经验分享;如何高效对接,高效开发
android
落落落sss14 小时前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis