当前位置:   article > 正文

Flutter18 Flutter 组件之 导航器 Route 详解_flutter route

flutter route

目录

1 简单页面跳转  

2.1 命名 Route 详解

2.2  路由跳转方式之 Push 详解

2.3  Navigator.push 

3 路由跳转方式之 Push 进阶

3.1 pushNamedAndRemoveUntil

3.2 pushReplacementNamed  = startActivity+finsh() 

3.3 popAndPushNamed

4 路由跳转方式之 Pop 详解

4.1 Navigator.pop

4.2 路由跳转方式之 Pop 进阶

5. 初始路由 initialRoute

6. 路由拦截 onGenerateRoute

7. 路由传值

8.1 路由正向传值以及反参接收

8.2 路由接收正向传值以及反向传参

8.3 其他写法


**首先:一个App可能有多个导航器Navigator

MaterialApp内置了一个导航器Navigator

1 简单页面跳转  

Navigator.of(context).pop VS Navigator.pop(context)

Navigator.of(context).push VS Navigator.push(context)

Navigator也是一个Widget    下面就会出现多个导航器

------ Navigator.of(context,rootNavigator)可以指定使用哪个导航器

  1. class InitPage extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. ///直接返回了一个Navigator对象
  5. return Navigator(
  6. //初始路由的名字
  7. initialRoute: 'pageOne',
  8. onGenerateRoute: (RouteSettings settings) {
  9. WidgetBuilder builder;
  10. switch (settings.name) {
  11. case 'pageOne':
  12. //pageOne的路由对应的页面
  13. builder = (BuildContext ctx) => PageOne();
  14. break;
  15. case 'pageTwo':
  16. //pageTwo的路由对应的页面
  17. builder = (BuildContext ctx) => PageTwo(
  18. onSignupComplete: () {
  19. ///PageTwo点击事件,跳转到DefaultPage页面
  20. //注意这个Navigator.of操作的是MaterialApp的内置Navigator,后面会有说明
  21. Navigator.of(context).pop();
  22. },
  23. );
  24. break;
  25. }
  26. return MaterialPageRoute(builder: builder, settings: settings);
  27. );
  28. }
  29. }

2.1 命名 Route 详解

  1. import 'package:flutter/material.dart';
  2. class FMMaterialAppVC extends StatelessWidget{
  3. @override
  4. Widget build(BuildContext context) {
  5. // TODO: implement build
  6. return MaterialApp(
  7. home: Scaffold(
  8. body: AAA(),
  9. ),
  10. routes: {
  11. '/bbb': (context) => BBB(),
  12. '/ccc': (context) => CCC(),
  13. '/ddd': (context) => DDD(),
  14. },
  15. );
  16. }
  17. }
  18. Navigator.pushNamed(context, '/bbb');
  19. //flutter pop回首页, 不管导航栈有多少路由
  20. Navigator.popUntil(context, (route) => route.isFirst);

2.2  路由跳转方式之 Push 详解

无参数

Navigator.pushNamed(context, '/bbb');

有参数

  1. final datas = {"data": ["1","2","3"]};
  2. Navigator.pushNamed(context, '/bbb', arguments: datas);

2.3  Navigator.push 

无参数

  1. Navigator.push(
  2. context,
  3. MaterialPageRoute(
  4. builder: (context){
  5. return BBB();
  6. }
  7. );

有参数,name 可以用来给路由命名,arguments 用来传递参数

  1. final datas = {"data": ["1","2","3"]};
  2. Navigator.push(
  3. context,
  4. MaterialPageRoute(
  5. builder: (context){
  6. return BBB();
  7. },
  8. settings: RouteSettings(
  9. name: '/bbb',
  10. arguments: datas,
  11. ),
  12. ),
  13. );

上面代码意思就是跳转到 BBB() 页面,并且给 BBB() 命名为 '/bbb',在路由堆栈中,读取到这个 route 时,route.setting.name 与该命名相同。

3 路由跳转方式之 Push 进阶

2 中是最为常用的页面进出栈,但是在某些场合需要有特殊的处理。
注意:写法大同小异,后续就不在赘述传参方式,均与2相同。

3.1 pushNamedAndRemoveUntil

例如我们页面从AAA->BBB->CCC->DDD,这样进行页面,但是我们希望 CCC 再使用过后就被销毁。使得页面层级变为 AAA-BBB-DDD。

Navigator.of(context).pushNamedAndRemoveUntil('/ddd', (route) => route.settings.name == '/bbb');

跳转到指定页面,并删除前边所有页面

  1. Navigator.of(context).pushNamedAndRemoveUntil('/ddd', (route) => route.isCurrent)
  2. // 等价于下面这行代码
  3. //Navigator.of(context).pushNamedAndRemoveUntil('/ddd', (route) => route.settings.name == '/ddd');

3.2 pushReplacementNamed  = startActivity+finsh() 

先跳转再处理路径

例如我们页面从AAA->BBB->CCC->DDD,这样进行页面,但是我们希望 CCC 再使用过后就被销毁。使得页面层级变为 AAA-BBB-DDD。

            Navigator.pushReplacementNamed(context, '/ddd');

3.3 popAndPushNamed

先 pop 一级,然后在 push 到对应页面,效果与3.2 相同

            Navigator.popAndPushNamed(context, '/ddd');

4 路由跳转方式之 Pop 详解

Navigator.pop(context);

 判断是否可以 pop

  1. bool canpop = Navigator.canPop(context);
  2. if (canpop) Navigator.pop(context);

先判断是否可以 pop,如果可以,在pop,相当于 上边代码

Navigator.maybePop(context);

4.1 Navigator.pop

无参数

            Navigator.pop(context);

有参数

  1. final data = {"data":["1","2","3"]};
  2. Navigator.pop(context, data);

4.2 路由跳转方式之 Pop 进阶

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');

5. 初始路由 initialRoute

  1. Widget build(BuildContext context) {
  2. // TODO: implement build
  3. return MaterialApp(
  4. // home: Scaffold(
  5. // body: AAA(),
  6. // ),
  7. initialRoute: '/ccc',
  8. routes: {
  9. '/aaa': (context) => AAA(),
  10. '/bbb': (context) => BBB(),
  11. '/ccc': (context) => CCC(),
  12. '/ddd': (context) => DDD(),
  13. },
  14. );
  15. }
  • a. 更改 initialRoute 为 routes 表里命名过得路由。

  • b. 设置根路由
    设置路由 '/' ,当初始路由异常时,会停留在根路由。

  • c. 使用未知路由
    1. Widget build(BuildContext context) {
    2. // TODO: implement build
    3. return MaterialApp(
    4. // home: Scaffold(
    5. // body: AAA(),
    6. // ),
    7. initialRoute: '/cc',
    8. routes: {
    9. '/aaa': (context) => AAA(),
    10. '/bbb': (context) => BBB(),
    11. '/ccc': (context) => CCC(),
    12. '/ddd': (context) => DDD(),
    13. },
    14. onUnknownRoute: (setting){
    15. print(setting);
    16. return MaterialPageRoute(builder: (context) => AAA());
    17. },
    18. );
    19. }

    6. 路由拦截 onGenerateRoute

  1. class FMMaterialAppVC extends StatelessWidget{
  2. @override
  3. Widget build(BuildContext context) {
  4. // TODO: implement build
  5. return MaterialApp(
  6. // home: Scaffold(
  7. // body: AAA(),
  8. // ),
  9. initialRoute: '/',
  10. routes: {
  11. '/': (context) => AAA(),
  12. '/bbb': (context) => BBB(),
  13. '/ccc': (context) => CCC(),
  14. '/ddd': (context) => DDD(),
  15. },
  16. // onGenerateInitialRoutes: (string){
  17. // return [
  18. // MaterialPageRoute(builder: (context) => AAA()),
  19. // ];
  20. // },
  21. onGenerateRoute: (setting){
  22. print(setting);
  23. return MaterialPageRoute(builder: (context) => CCC());
  24. },
  25. onUnknownRoute: (setting){
  26. print(setting);
  27. return MaterialPageRoute(builder: (context) => AAA());
  28. },
  29. );
  30. }
  31. }

应该有很多小伙伴跟我一样,onGenerateRoute 不执行,明明写了 onGenerateRoute 方法,但是却不响应。查了挺多博客,没有相关描述,然后去翻了官方文档和源码,终于找到问题。

onGenerateRoute 路由拦截不能与命名路由一起使用,否则会只执行命名路由,不在进行拦截。下面我们注释掉命名路由,然后通过路由拦截,自定义一套路由跳转,从而实现命名路由的功能。

  1. Widget build(BuildContext context) {
  2. // TODO: implement build
  3. return MaterialApp(
  4. initialRoute: '/',
  5. // routes: {
  6. // '/': (context) => AAA(),
  7. // '/bbb': (context) => BBB(),
  8. // '/ccc': (context) => CCC(),
  9. // '/ddd': (context) => DDD(),
  10. // },
  11. // onGenerateInitialRoutes: (string){
  12. // return [
  13. // MaterialPageRoute(builder: (context) => AAA()),
  14. // ];
  15. // },
  16. onGenerateRoute: (setting){
  17. print(setting);
  18. final isLogin = true;
  19. final routes = {
  20. '/': (context) => AAA(),
  21. '/bbb': (context) => BBB(),
  22. '/ccc': (context) => CCC(),
  23. '/ddd': (context) => DDD(),
  24. };
  25. if (!isLogin) {
  26. return MaterialPageRoute(builder: (context) => AAA());
  27. }
  28. return MaterialPageRoute(builder: routes[setting.name], settings: setting);
  29. },
  30. onUnknownRoute: (setting){
  31. print(setting);
  32. return MaterialPageRoute(builder: (context) => AAA());
  33. },
  34. );
  35. }

7. 路由传值

8.1 路由正向传值以及反参接收

BBB 页面 push 到 CCC,并等待 CCC 回来时的反参。

  1. class BBB extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. // TODO: implement build
  5. return Scaffold(
  6. appBar: AppBar(
  7. title: Text('BBB'),
  8. ),
  9. body: Center(
  10. child: RaisedButton(
  11. child: Text('点击前往CCC'),
  12. onPressed: (){
  13. var backValueFromDDD = Navigator.pushNamed(context, '/ccc',arguments: {'value': "我是BBB页面传过来的值"});
  14. backValueFromDDD.then((value){
  15. print("CCC 传回来反参了,${value}");
  16. });
  17. // Navigator.pushNamedAndRemoveUntil(context, '/ccc', (route) => route.isCurrent);
  18. },
  19. ),
  20. ),
  21. );
  22. }
  23. }

我们使用 then 属性来接收下一个页面 pop 回来带的参数。

8.2 路由接收正向传值以及反向传参

我们在 CCC 类中增加以下代码。

  1. Widget build(BuildContext context) {
  2. // TODO: implement build
  3. var value = ModalRoute.of(context).settings.arguments;
  4. print("BBB 页面带过来参数了,${value}");
  5. return Scaffold(
  6. appBar: AppBar(
  7. title: Text('CCC'),
  8. ),
  9. body: _listView(context),
  10. );
  11. }
  1. ListTile(
  2. title: Text("Navigator.of(context).pop 传参"),
  3. onTap: (){
  4. Navigator.of(context).pop({"value":"我是CCC页面带回来的值"});
  5. },
  6. ),

8.3 其他写法

在 BBB 中可以尝试以下写法,可以达到相同效果。

  1. class BBB extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. // TODO: implement build
  5. return Scaffold(
  6. appBar: AppBar(
  7. title: Text('BBB'),
  8. ),
  9. body: Center(
  10. child: RaisedButton(
  11. child: Text('点击前往CCC'),
  12. onPressed: () async {
  13. var backValueFromDDD = await Navigator.pushNamed(context, '/ccc',arguments: {'value': "我是BBB页面传过来的值"});
  14. backValueFromDDD;
  15. print(backValueFromDDD);
  16. // Navigator.pushNamedAndRemoveUntil(context, '/ccc', (route) => route.isCurrent);
  17. },
  18. ),
  19. ),
  20. );
  21. }
  22. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/995728
推荐阅读
相关标签
  

闽ICP备14008679号