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的内容。

运行起来看看吧!

相关推荐
健了个平_243 小时前
iOS 26 适配笔记
ios·swift·wwdc
小镇学者5 小时前
【PHP】导入excel 报错Trying to access array offset on value of type int
android·php·excel
Digitally7 小时前
如何将数据从 iPhone 传输到笔记本电脑
ios·电脑·iphone
一笑的小酒馆8 小时前
Android11 Launcher3去掉抽屉改为单层
android
白玉cfc9 小时前
【iOS】cell的复用以及自定义cell
ios·cocoa·xcode
AD钙奶-lalala10 小时前
在 macOS 上搭建 Flutter 开发环境
flutter·macos
louisgeek10 小时前
Git 根据不同目录设置不同账号
android
星释11 小时前
使用Appium在iOS上实现自动化
ios·appium·自动化
qq_3909347412 小时前
MySQL中的系统库(简介、performance_schema)
android·数据库·mysql
whysqwhw12 小时前
Kotlin Flow 实现响应式编程指南
android