赞
踩
目录
3.2 pushReplacementNamed = startActivity+finsh()
**首先:一个App可能有多个导航器Navigator
MaterialApp内置了一个导航器Navigator
Navigator.of(context).pop VS Navigator.pop(context)
Navigator.of(context).push VS Navigator.push(context)
Navigator也是一个Widget 下面就会出现多个导航器
------ Navigator.of(context,rootNavigator)可以指定使用哪个导航器
-
- class InitPage extends StatelessWidget {
- @override
- Widget build(BuildContext context) {
- ///直接返回了一个Navigator对象
- return Navigator(
- //初始路由的名字
- initialRoute: 'pageOne',
- onGenerateRoute: (RouteSettings settings) {
- WidgetBuilder builder;
- switch (settings.name) {
- case 'pageOne':
- //pageOne的路由对应的页面
- builder = (BuildContext ctx) => PageOne();
- break;
- case 'pageTwo':
- //pageTwo的路由对应的页面
- builder = (BuildContext ctx) => PageTwo(
- onSignupComplete: () {
- ///PageTwo点击事件,跳转到DefaultPage页面
- //注意这个Navigator.of操作的是MaterialApp的内置Navigator,后面会有说明
- Navigator.of(context).pop();
- },
- );
- break;
- }
- return MaterialPageRoute(builder: builder, settings: settings);
- );
- }
- }
- import 'package:flutter/material.dart';
-
- class FMMaterialAppVC extends StatelessWidget{
- @override
- Widget build(BuildContext context) {
- // TODO: implement build
- return MaterialApp(
- home: Scaffold(
- body: AAA(),
- ),
- routes: {
- '/bbb': (context) => BBB(),
- '/ccc': (context) => CCC(),
- '/ddd': (context) => DDD(),
- },
- );
- }
- }
- Navigator.pushNamed(context, '/bbb');
- //flutter pop回首页, 不管导航栈有多少路由
- Navigator.popUntil(context, (route) => route.isFirst);
无参数
Navigator.pushNamed(context, '/bbb');
有参数
- final datas = {"data": ["1","2","3"]};
- Navigator.pushNamed(context, '/bbb', arguments: datas);
无参数
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context){
- return BBB();
- }
- );
有参数,name 可以用来给路由命名,arguments 用来传递参数
- final datas = {"data": ["1","2","3"]};
-
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context){
- return BBB();
- },
- settings: RouteSettings(
- name: '/bbb',
- arguments: datas,
- ),
- ),
- );
上面代码意思就是跳转到 BBB() 页面,并且给 BBB() 命名为 '/bbb',在路由堆栈中,读取到这个 route 时,route.setting.name 与该命名相同。
2 中是最为常用的页面进出栈,但是在某些场合需要有特殊的处理。
注意:写法大同小异,后续就不在赘述传参方式,均与2相同。
例如我们页面从AAA->BBB->CCC->DDD,这样进行页面,但是我们希望 CCC 再使用过后就被销毁。使得页面层级变为 AAA-BBB-DDD。
Navigator.of(context).pushNamedAndRemoveUntil('/ddd', (route) => route.settings.name == '/bbb');
跳转到指定页面,并删除前边所有页面
- Navigator.of(context).pushNamedAndRemoveUntil('/ddd', (route) => route.isCurrent)
- // 等价于下面这行代码
- //Navigator.of(context).pushNamedAndRemoveUntil('/ddd', (route) => route.settings.name == '/ddd');
先跳转再处理路径
例如我们页面从AAA->BBB->CCC->DDD,这样进行页面,但是我们希望 CCC 再使用过后就被销毁。使得页面层级变为 AAA-BBB-DDD。
Navigator.pushReplacementNamed(context, '/ddd');
先 pop 一级,然后在 push 到对应页面,效果与3.2 相同
Navigator.popAndPushNamed(context, '/ddd');
Navigator.pop(context);
判断是否可以 pop
- bool canpop = Navigator.canPop(context);
- if (canpop) Navigator.pop(context);
先判断是否可以 pop,如果可以,在pop,相当于 上边代码
Navigator.maybePop(context);
无参数
Navigator.pop(context);
有参数
- final data = {"data":["1","2","3"]};
- Navigator.pop(context, data);
4 中是最为常用的页面进出栈,但是在某些场合需要有特殊的处理。pop 进阶方法比较少,只有 popUntil (2.1)与 popAndPushNamed ,在3.3中讲过后者了,这里不重复叙述。
Navigator.popUntil(context, (route) => route.isFirst);
我们使用下方代码回到 BBB 页面 AAA-BBB-CCC-DDD -> AAA-BBB
Navigator.popUntil(context, (route) => route.settings.name == '/bbb');
- Widget build(BuildContext context) {
- // TODO: implement build
- return MaterialApp(
- // home: Scaffold(
- // body: AAA(),
- // ),
- initialRoute: '/ccc',
- routes: {
- '/aaa': (context) => AAA(),
- '/bbb': (context) => BBB(),
- '/ccc': (context) => CCC(),
- '/ddd': (context) => DDD(),
- },
- );
- }
a. 更改 initialRoute 为 routes 表里命名过得路由。
b. 设置根路由
设置路由 '/' ,当初始路由异常时,会停留在根路由。
- Widget build(BuildContext context) {
- // TODO: implement build
- return MaterialApp(
- // home: Scaffold(
- // body: AAA(),
- // ),
- initialRoute: '/cc',
- routes: {
- '/aaa': (context) => AAA(),
- '/bbb': (context) => BBB(),
- '/ccc': (context) => CCC(),
- '/ddd': (context) => DDD(),
- },
- onUnknownRoute: (setting){
- print(setting);
- return MaterialPageRoute(builder: (context) => AAA());
- },
- );
- }
- class FMMaterialAppVC extends StatelessWidget{
- @override
- Widget build(BuildContext context) {
- // TODO: implement build
- return MaterialApp(
- // home: Scaffold(
- // body: AAA(),
- // ),
- initialRoute: '/',
- routes: {
- '/': (context) => AAA(),
- '/bbb': (context) => BBB(),
- '/ccc': (context) => CCC(),
- '/ddd': (context) => DDD(),
- },
- // onGenerateInitialRoutes: (string){
- // return [
- // MaterialPageRoute(builder: (context) => AAA()),
- // ];
- // },
- onGenerateRoute: (setting){
- print(setting);
- return MaterialPageRoute(builder: (context) => CCC());
- },
- onUnknownRoute: (setting){
- print(setting);
- return MaterialPageRoute(builder: (context) => AAA());
- },
- );
- }
- }
应该有很多小伙伴跟我一样,onGenerateRoute 不执行,明明写了 onGenerateRoute 方法,但是却不响应。查了挺多博客,没有相关描述,然后去翻了官方文档和源码,终于找到问题。
onGenerateRoute 路由拦截不能与命名路由一起使用,否则会只执行命名路由,不在进行拦截。下面我们注释掉命名路由,然后通过路由拦截,自定义一套路由跳转,从而实现命名路由的功能。
- Widget build(BuildContext context) {
- // TODO: implement build
- return MaterialApp(
- initialRoute: '/',
- // routes: {
- // '/': (context) => AAA(),
- // '/bbb': (context) => BBB(),
- // '/ccc': (context) => CCC(),
- // '/ddd': (context) => DDD(),
- // },
- // onGenerateInitialRoutes: (string){
- // return [
- // MaterialPageRoute(builder: (context) => AAA()),
- // ];
- // },
- onGenerateRoute: (setting){
- print(setting);
- final isLogin = true;
-
- final routes = {
- '/': (context) => AAA(),
- '/bbb': (context) => BBB(),
- '/ccc': (context) => CCC(),
- '/ddd': (context) => DDD(),
- };
-
- if (!isLogin) {
- return MaterialPageRoute(builder: (context) => AAA());
- }
-
- return MaterialPageRoute(builder: routes[setting.name], settings: setting);
- },
- onUnknownRoute: (setting){
- print(setting);
- return MaterialPageRoute(builder: (context) => AAA());
- },
- );
- }
BBB 页面 push 到 CCC,并等待 CCC 回来时的反参。
- class BBB extends StatelessWidget {
- @override
- Widget build(BuildContext context) {
- // TODO: implement build
- return Scaffold(
- appBar: AppBar(
- title: Text('BBB'),
- ),
- body: Center(
- child: RaisedButton(
- child: Text('点击前往CCC'),
- onPressed: (){
- var backValueFromDDD = Navigator.pushNamed(context, '/ccc',arguments: {'value': "我是BBB页面传过来的值"});
- backValueFromDDD.then((value){
- print("CCC 传回来反参了,${value}");
- });
- // Navigator.pushNamedAndRemoveUntil(context, '/ccc', (route) => route.isCurrent);
- },
- ),
- ),
- );
- }
- }
我们使用 then 属性来接收下一个页面 pop 回来带的参数。
我们在 CCC 类中增加以下代码。
- Widget build(BuildContext context) {
- // TODO: implement build
- var value = ModalRoute.of(context).settings.arguments;
- print("BBB 页面带过来参数了,${value}");
-
- return Scaffold(
- appBar: AppBar(
- title: Text('CCC'),
- ),
- body: _listView(context),
- );
- }
- ListTile(
- title: Text("Navigator.of(context).pop 传参"),
- onTap: (){
- Navigator.of(context).pop({"value":"我是CCC页面带回来的值"});
- },
- ),
在 BBB 中可以尝试以下写法,可以达到相同效果。
- class BBB extends StatelessWidget {
- @override
- Widget build(BuildContext context) {
- // TODO: implement build
- return Scaffold(
- appBar: AppBar(
- title: Text('BBB'),
- ),
- body: Center(
- child: RaisedButton(
- child: Text('点击前往CCC'),
- onPressed: () async {
- var backValueFromDDD = await Navigator.pushNamed(context, '/ccc',arguments: {'value': "我是BBB页面传过来的值"});
- backValueFromDDD;
- print(backValueFromDDD);
- // Navigator.pushNamedAndRemoveUntil(context, '/ccc', (route) => route.isCurrent);
- },
- ),
- ),
- );
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。