转载请注明出处: https://learnandfish.com/

概述

每个应用都有很多个页面,在flutter中同样也有很多页面,被称之为路由(Router),页面之间的跳转通过导航器(Navigator)进行管理。
其中 Navigator.push 和 Navigator.pop 是最简单的跳转到新页面和返回到上一级界面的方式。

路由分为静态路由(即命名路由)和动态路由。页面之间跳转时往往需要传递参数,这称之为路由传值。下面我们会一一带领大家学习。

通过本篇文章的学习我们的目标是熟练掌握路由及传值,以后进行应用开发时对页面跳转方面不再疑惑。

静态路由(即命名路由)

flutter中万物皆widget,我们的页面(route)也是widget的子类,所以我们定义一个界面也是通过继承widget实现。
前面的博客我们已经定义过界面了,比如计数器实例,就是一个简单的页面,也就是一个路由。下面我们来详细实现一个界面。
首先我需要一个入口函数,这个相信大家已经很熟悉了,就是在main方法中调用runApp函数进入应用,我们就不做详细介绍了,直接给出代码。

import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {// 常用固定写法,生成Material风格的Appreturn MaterialApp(title: "路由使用",theme: ThemeData(// 默认为亮色主题,可以设置[Brightness.dark]变成黑暗模式brightness: Brightness.light,),home: HomePage(), // 首页面);}
}class HomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {// 通过Scaffold可以方便的生成一个Material风格的页面return Scaffold(// 顶部导航栏appBar: AppBar(title: Text("主页面"),),body: Center(child: RaisedButton(child: Text("我是第一个界面,点击我进入第二个界面"),onPressed: () {print("我是第一个界面,点击我进入第二个界面");},),),);}
}

上面的代码是我们最常规的包含一个主页面的应用。后续我们写应用时候的基本框架也是在此基础上进行扩展。
现在我们的想法是点击这个页面上的按钮跳转的第二个界面,首先我们需要构造第二个界面。构造第二个界面其实和我们构造第一个
界面HomePage一样,继承widget重写自己想要的样式即可。实现了页面就要开始跳转逻辑。

静态路由即命名路由,在通过Navigator进行跳转之前,需要在MaterialApp组件内显式声明路由的名称,一旦声明,路由的跳转
方式就固定了,所以称之为静态路由,有唯一的名称所以也称之为命令路由。显式声明路由通过在MaterialApp内的routes属性进行定义。

如果我们有很多个页面和很多个其他类型的组件都放在lib下,对于后期维护简直是一大折磨,所以分包是大多数平台的常规操作,
就是对有同一种特性的东西放置在同一个包下,比如页面类的组件都放在pages包,工具类的组件放在utils包下等。
接下来我们就新建一个pages包,把第二个界面SecondPage放进去,把第一个界面HomePage也提取出来放到这个包下。

我们分为一下三步进行静态路由的跳转:

  • 首先在lib目录右键新建pages包,接着在pages包下新建SecondPage.dart文件,然后把HomePage提取到pages下,成为单独的类。
  • 在RouteDemo类中的MaterialApp内声明routes属性,为了显示声明路由的名称。
  • 使用Navigator进行页面的跳转和返回。
import 'package:flutter/material.dart';// 引入页面路径
import 'pages/HomePage.dart';
import 'pages/SecondPage.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {// 常用固定写法,生成Material风格的Appreturn MaterialApp(title: "路由使用",theme: ThemeData(// 默认为亮色主题,可以设置[Brightness.dark]变成黑暗模式brightness: Brightness.light,),// 默认加载的页面initialRoute: '/', // 首页面// 显式声明界面列表routes: {'/': (context) => HomePage(),'/secondPage': (context) => SecondPage(),},);}
}

首页面单独提取出来之后的代码如下。

import 'package:flutter/material.dart';class HomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {// 通过Scaffold可以方便的生成一个Material风格的页面return Scaffold(// 顶部导航栏appBar: AppBar(title: Text("主页面"),),body: Center(child: RaisedButton(child: Text("我是第一个界面,点击我进入第二个界面"),onPressed: () {print("我是第一个界面,点击我进入第二个界面");// 跳转到第二个界面Navigator.pushNamed(context, '/secondPage');},),),);}
}

第二个页面提取之后的代码。

import 'package:flutter/material.dart';class SecondPage extends StatelessWidget {@overrideWidget build(BuildContext context) {// 通过Scaffold可以方便的生成一个Material风格的页面return Scaffold(// 顶部导航栏appBar: AppBar(title: Text("第二个界面"),),body: Center(child: RaisedButton(child: Text("我是第二个界面,点击我进入第二个界面"),onPressed: () {print("我是第二个界面,点击我返回到第一个界面");// 返回上一个界面Navigator.pop(context);},),),);}
}

对于命名路由的跳转,通过Navigator.pushNamed方法调用,通过Navigator.pop方法返回上一级界面。

动态路由

动态路由不需要显示声明,直接通过代码实现。

class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {// 常用固定写法,生成Material风格的Appreturn MaterialApp(title: "路由使用",theme: ThemeData(// 默认为亮色主题,可以设置[Brightness.dark]变成黑暗模式brightness: Brightness.light,),home: HomePage(),);}
}

在HomePage界面通过调用Navigator.push方法实现跳转。第二个页面的返回逻辑不变。

Navigator.push(context,MaterialPageRoute(builder: (context) => SecondPage(),));

动态路由的相互传参

有时候我们不仅需要跳转到对应界面,还需要传递一些参数给下一个界面,同时下一个界面返回时,把某些参数再次传递给该界面。
我们修改SecondPage组件的构造方法,为了接收需要传递的参数。这时候我们第二个页面结构如下:

class SecondPage extends StatelessWidget {// 定义一个需要变量, 接收传递的参数final String title;// 为title设置一个默认参数,这样的跳转该界面时可以不传值。SecondPage({Key key, this.title = "第二个界面"});@overrideWidget build(BuildContext context) {// 通过Scaffold可以方便的生成一个Material风格的页面return Scaffold(// 顶部导航栏appBar: AppBar(title: Text(title),),body: Center(child: RaisedButton(child: Text("我是第二个界面,点击我进入第二个界面"),onPressed: () {print("我是第二个界面,点击我返回到第一个界面");// 返回上一个界面Navigator.pop(context);},),),);}
}

第一个界面跳转的地方代码是这样的。

Navigator.push(context,MaterialPageRoute(// 传递title为SecondPage,跳转到第二个界面就会把标题设置为SecondPagebuilder: (context) => SecondPage(title: "SecondPage"),));},

说完了从第一个页面往第二个页面传递了参数,如果第二个页面返回时传递一句话,然后第一个页面接收到这句话然后打印出来,
代码修改如下:

// HomePage页面代码
Navigator.push(context,MaterialPageRoute(// 传递title为SecondPage,跳转到第二个界面就会把标题设置为SecondPagebuilder: (context) => SecondPage(title: "SecondPage"),// 调用then等待接收返回数据)).then((value) => print(value));// SecondPage页面代码Navigator.pop(context, "返回传递数据");

静态路由(即命名路由)的相互传参

讲完了动态路由及动态路由传参之后,我们来讲一下静态路由传参,参数的传递方式是flutter为我们定义好的,我们只需要把固定
代码拷贝回来,稍微修改即可。为了更具有普遍性,我们再定义一个页面ThirdPage。

在我们显示声明了routes之后,还需要在MaterialApp组件内添加onGenerateRoute属性内容进行参数传递的处理。
完整代码如下:

import 'package:flutter/material.dart';import 'pages/HomePage.dart';
import 'pages/SecondPage.dart';
import 'pages/ThirdPage.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {// 声明所有的页面final routes = {'/': (context, {arguments}) => HomePage(),'/secondPage': (context, {arguments}) => SecondPage(),'/thirdPage': (context, {arguments}) => ThirdPage(arguments: arguments),};@overrideWidget build(BuildContext context) {// 常用固定写法,生成Material风格的Appreturn MaterialApp(title: "路由使用",theme: ThemeData(// 默认为亮色主题,可以设置[Brightness.dark]变成黑暗模式brightness: Brightness.light,),
//      home: HomePage(),initialRoute: '/', // 默认界面// 当页面跳转时进行参数处理onGenerateRoute: (RouteSettings settings) {// 获取声明的路由页面函数var pageBuilder = routes[settings.name];if (pageBuilder != null) {if (settings.arguments != null) {// 创建路由页面并携带参数return MaterialPageRoute(builder: (context) =>pageBuilder(context, arguments: settings.arguments));} else {return MaterialPageRoute(builder: (context) => pageBuilder(context));}}return MaterialPageRoute(builder: (context) => HomePage());},);}
}

第二个页面传递参数时使用Navigator.pushNamed方法,具体代码如下:

import 'package:flutter/material.dart';class SecondPage extends StatelessWidget {// 定义一个需要变量, 接收传递的参数final String title;// 为title设置一个默认参数,这样的跳转该界面时可以不传值。SecondPage({Key key, this.title = "第二个界面"});@overrideWidget build(BuildContext context) {// 通过Scaffold可以方便的生成一个Material风格的页面return Scaffold(// 顶部导航栏appBar: AppBar(title: Text(title),),body: Center(child: RaisedButton(child: Text("我是第二个界面,点击我进入第二个界面"),onPressed: () {print("我是第二个界面,点击我进入第三个界面");// 通过arguments指定参数Navigator.pushNamed(context, "/thirdPage",arguments: {'title': "命令路由传递过来的title"});},),),);}
}

第三个页面获取参数,完整代码如下:

import 'package:flutter/material.dart';class ThirdPage extends StatelessWidget {final Map arguments;// 为title设置一个默认参数,这样的跳转该界面时可以不传值。ThirdPage({Key key, this.arguments});@overrideWidget build(BuildContext context) {// 通过Scaffold可以方便的生成一个Material风格的页面return Scaffold(// 顶部导航栏appBar: AppBar(title: Text("${arguments != null ? arguments['title'] : "ThirdPage"}"),),body: Center(child: RaisedButton(child: Text("我是第三个界面,点击我进入第二个界面"),onPressed: () {print("我是第三个界面,点击我返回到第二个界面");// 返回上一个界面Navigator.pop(context, "返回传递数据Page3");},),),);}
}

命名路由传参优化

上面我们已经实现了参数的传递,但是routes页面列表和onGenerateRoute比较固定,我们能够把这两个单独提取出来成为
一个单独的类,这样后期再创建页面或者维护的时候只需要修改这一个类就行了。

我们新建一个PageConstants类,进行提取,修改后的代码如下:

import 'package:flutter/material.dart';// 引入页面路径
import '../pages/HomePage.dart';
import '../pages/SecondPage.dart';
import '../pages/ThirdPage.dart';// 声明所有页面
final routes = {'/': (context, {arguments}) => HomePage(),'/secondPage': (context, {arguments}) => SecondPage(),'/thirdPage': (context, {arguments}) => ThirdPage(arguments: arguments),
};// 处理参数传递
// ignore: top_level_function_literal_block
var onGenerateRoute = (RouteSettings settings) {// 获取声明的路由页面函数var pageBuilder = routes[settings.name];if (pageBuilder != null) {if (settings.arguments != null) {// 创建路由页面并携带参数return MaterialPageRoute(builder: (context) =>pageBuilder(context, arguments: settings.arguments));} else {return MaterialPageRoute(builder: (context) => pageBuilder(context));}}return MaterialPageRoute(builder: (context) => HomePage());
};

这时候我们只需要简单修改MyApp组件即可:

import 'package:flutter/material.dart';
import 'package:hello_flutter/pages/PageConstants.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {// 常用固定写法,生成Material风格的Appreturn MaterialApp(title: "路由使用",theme: ThemeData(// 默认为亮色主题,可以设置[Brightness.dark]变成黑暗模式brightness: Brightness.light,),initialRoute: '/', // 默认界面// 通过PageConstants引入onGenerateRoute: onGenerateRoute,);}
}

这样来看就会清爽很多。

篇幅所限,这次的内容就先讲到这里,下篇文章继续讲往后的内容,应该会单独讲一讲实现仿闲鱼底部tab页面切换和仿头条多tab页切换。

为了第一时间获取最新文章,请关注公众号 -- 程序员指北,每一个关注都能让作者多搬一块砖。

flutter 返回指定界面_Flutter页面路由导航及传参相关推荐

  1. 一篇文章说完Flutter页面路由导航及传参

    目录 前言 动态路由 静态路由 静态路由传参 Fluro 实现路由导航与传参 前言 在 Flutter 中,App 多个页面之间的跳转是由 Navigator(导航器)来管理的,如常见的 Naviga ...

  2. flutter 返回指定界面_Flutter 即学即用系列博客——04 Flutter UI 初窥

    前面三篇可以算是一个小小的里程碑. 主要是介绍了 Flutter 环境的搭建.如何创建 Flutter 项目以及如何在旧有 Android 项目引入 Flutter. 这一篇我们来学习下 Flutte ...

  3. 微信小程序开发:学习笔记[8]——页面跳转及传参

    微信小程序开发:学习笔记[8]--页面跳转及传参 页面跳转 一个小程序拥有多个页面,我们可以通过wx.navigateTo推入一个新的页面.在首页使用2次wx.navigateTo后,页面层级会有三层 ...

  4. React学习:路由定义及传参、数据复用-学习笔记

    文章目录 React学习:路由定义及传参.数据复用-学习笔记 在React中使用react-router-dom路由 简单例子 路由定义及传参 React学习:路由定义及传参.数据复用-学习笔记 在R ...

  5. JavaScript在表格指定的位置插入和删除(传参)

    开发工具与关键技术:DW和JavaScript 撰写时间:2019年1月17日 JavaScript在表格指定的位置插入和删除(传参) 1.先为页面设计Html 网页上出现的效果: 2.要实现插入行, ...

  6. vue路由跳转传参乱码解决

    vue路由组件跳转传参中文乱码解决 -在路由传参 this.$router.push({path:"/index", query:{msg:encodeURI("我是消息 ...

  7. vue中路由传参方式之二(this.$router.push进行编程式路由跳转传参)

    this.$router.push进行编程式路由跳转传参 router中路由配置 组件home点击传参 组件homeDetails接受参数 router中路由配置 params第一种传参路由配置 {p ...

  8. vue 传参 微信_小猿圈web前端之微信小程序页面间跳转传参方式总结

    原标题:小猿圈web前端之微信小程序页面间跳转传参方式总结 最近小程序发展的越来越快,很多大公司也在打造自己的小程序平台以及购物小程序等等,今天小猿圈web前端讲师就总结了关于微信小程序的知识点,首先 ...

  9. VUE路由跳转传参的七种方法

    vue中每个页面都需要在路由中声明,就是在router/index.js中写 import Vue from 'vue' import Router from 'vue-router' import ...

最新文章

  1. Leetcode: Reorder List
  2. 如何查看华为EMUI系统APK源码?
  3. 简单了解各种序列化技术-XML序列化框架介绍
  4. [Swift]LeetCode551. 学生出勤纪录 I | Student Attendance Record I
  5. javascript 内存回收机制
  6. js与c语言效率_JavaScript控制流及关键字与C语言之比较
  7. 浅谈auto与decltype函数的区别
  8. 哪个linux桌面有电池显示,(求助!!!)进ubuntu后桌面只显示左上角!(已解决)...
  9. thinkphp数据库连接池_Thinkphp5框架下的数据库连接
  10. IBM Racetrack内存为移动设备带来1TB容量
  11. 56)函数模板的基本语法
  12. android bmob上传图片,Bmob+Android+ECharts 实现移动端数据上传与图表展示
  13. 功能覆盖率与代码覆盖率区别
  14. 插画师所需的基础软件
  15. 【做题笔记】P2327 [SCOI2005]扫雷
  16. 科大讯飞Windows麦克风监听语音唤醒+语音识别demo
  17. < 开源项目框架:推荐几个开箱即用的开源管理系统 - 让开发不再复杂 >
  18. 哪种灯对眼睛视力保护最好?盘点五款全光谱光照的护眼台灯
  19. QT5.12+opencv4.0.1 Cielab空间 像素颜色信息
  20. java web实现拨打电话_java的webservice实现电话号码查询

热门文章

  1. Java 8日期时间API教程:LocalDateTime
  2. Java 8 Lambda演练
  3. Spring MVC开发–快速教程
  4. Struts2的配置文件struts.xml的模板
  5. 判断选择语句switch...case
  6. petalinux 配置_澧县高压管道工厂化配置专业销售
  7. android webviwe 头布局,Android布局问题,带有WebView下方的按钮
  8. jsp mysql servlet_JSP+Servlet+JDBC+mysql实现的学生成绩管理系统
  9. LeetCode 03. 无重复字符的最长子串
  10. python页面驱动mxd_如何利用python 批量导出mxd至jpg