路由 Navigator

2022/11/27 Flutter路由

本文介绍Flutter的路由配置和使用,并且实现简单的案例。

# 匿名路由

  • 路由传值

    • 传递可以在初始新界面对象时通过构造函数压入
    • 新界面退出后的返回值通过 Navigator.pop 的参数返回
  • 定义

    MaterialPageRoute({
      // 是一个WidgetBuilder类型的回调函数,它的作用是构建路由页面的具体内容,返回值是一个widget。我们通常要实现此回调,返回新路由的实例。
      WidgetBuilder builder,
    
      // 包含路由的配置信息,如路由名称、是否初始路由(首页)。
      RouteSettings settings,
    
      // 默认情况下,当入栈一个新路由时,原来的路由仍然会被保存在内存中,如果想在路由没用的时候释放其所占用的所有资源,可以设置maintainState为 false。
      bool maintainState = true,
    
      // 表示新的路由页面是否是一个全屏的模态对话框,在 iOS 中,如果fullscreenDialog为true,新页面将会从屏幕底部滑入(而不是水平方向)。
      bool fullscreenDialog = false,
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  • 示例

    • 父页面
    import 'package:flutter/material.dart';
    import 'package:flutter_application_1/date_child.dart';
    
    void main(List<String> args) {
      runApp(const ModelBox());
    }
    
    class ModelBox extends StatelessWidget {
      const ModelBox({Key? key}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Box Model'),
            ),
            body: Column(
              children: const [
                ParentWidget(),
              ],
            )),
        );
      }
    }
    
    class ParentWidget extends StatelessWidget {
      const ParentWidget({Key? key}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Container(
          child: TextButton(
            onPressed: () async {
              print('object');
              var result = await Navigator.push(context,
                MaterialPageRoute(builder: (context) {
                  return const DateChildWidget(title: '父组件给你的名字');
                })
              );
              print(result);
            },
            child: const Text('跳转child')),
        );
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    • 子页面
    import 'package:flutter/material.dart';
    
    class DateChildWidget extends StatelessWidget {
      final String? title;
      const DateChildWidget({Key? key, this.title}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Datechild'),
          ),
          body: Column(
            children: [
              const Text('这是子页面'),
              ElevatedButton(
                onPressed: () {
                  Navigator.pop(context, 'ok');
                },
                child: const Text('返回父页面'))
            ],
          ),
        );
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

# 命名路由

  • 定义路由名称

    import 'package:flutter/material.dart';
    import 'package:flutter_application_1/date_child.dart';
    
    void main(List<String> args) {
      runApp(const ModelBox());
    }
    
    class ModelBox extends StatelessWidget {
      const ModelBox({Key? key}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return MaterialApp(
          routes: {
            '/child': (context) => const DateChildWidget(
              title: '命名路由',
            )
          },
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Box Model'),
            ),
            body: Column(
              children: const [
                ParentWidget()
              ],
            )),
        );
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
  • 跳转child

    class ParentWidget extends StatelessWidget {
      const ParentWidget({Key? key}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Container(
          child: TextButton(
            onPressed: () async {
              var result = await Navigator.pushNamed(
                context,
                '/child',
                arguments: {
                  'title': 'oiiiiiiiiiiiiiio'
                }
              );
            },
            child: const Text('跳转子路由')
          )
        );
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
  • 取值

    import 'package:flutter/material.dart';
    
    class DateChildWidget extends StatelessWidget {
      final String? title;
      const DateChildWidget({Key? key, this.title}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        // 取值
        final arguments = (ModalRoute.of(context)?.settings.arguments ?? <String, dynamic>{}) as Map;
        var title = arguments['title'];
        return Scaffold(
          appBar: AppBar(
            title: const Text('Datechild'),
          ),
          body: Column(
            children: [
              Text(title ?? ''),
              ElevatedButton(
                onPressed: () {
                  Navigator.pop(context, 'ok');
                },
                child: const Text('返回父页面')
              )
            ],
          ),
        );
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

# onGenerateRoute 手动解析

  • 示例
    import 'package:flutter/material.dart';
    
    void main(List<String> args) {
      runApp(const ModelBox());
    }
    
    class ModelBox extends StatelessWidget {
      const ModelBox({Key? key}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return MaterialApp(
          onGenerateRoute: (settings) {
            // 匹配/child
            if (settings.name == '/child') {
              return MaterialPageRoute(builder: (context) => const ChildPage());
            }
    
            // 匹配/detail/:id
            var uri = Uri.parse(settings.name!);
            print(uri);
            if (uri.pathSegments.length == 2 && uri.pathSegments.first == 'detail') {
              String uid = uri.pathSegments[1];
              return MaterialPageRoute(
                builder: (context) => DetailPage(uid: uid)
              );
            }
    
            // 404 娄底
            return MaterialPageRoute(builder: (context) => const UnknownPage());
          },
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Box Model'),
            ),
            body: Column(
              children: const [ParentWidget()],
            )),
        );
      }
    }
    
    class ChildPage extends StatelessWidget {
      const ChildPage({Key? key}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('123')),
          body: Container(
            child: Column(
              children: [
                const Text('首页'),
                OutlinedButton(
                  onPressed: () {
                    Navigator.pop(context, '回来了');
                  },
                  child: const Text('返回'))
              ],
            ),
          ),
        );
      }
    }
    
    class DetailPage extends StatelessWidget {
      final String? uid;
      const DetailPage({Key? key, this.uid}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Detail Page'),
          ),
          body: Text(uid ?? ''),
        );
      }
    }
    
    // 默认展示页面
    class ParentWidget extends StatelessWidget {
      const ParentWidget({Key? key}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Container(
            child: Column(
          children: [
            TextButton(
              onPressed: () async {
                var result = await Navigator.pushNamed(context, '/child',
                    arguments: {'title': 'oiiiiiiiiiiiiiio'});
              },
              child: const Text('跳转子路由')
            ),
            TextButton(
              onPressed: () async {
                var result = await Navigator.pushNamed(context, '/detail/id999');
              },
              child: const Text('跳转带参数/detail路由')
            ),
            TextButton(
              onPressed: () async {
                var result = await Navigator.pushNamed(context, '/detailsss');
              },
              child: const Text('跳转404')
            )
          ],
        ));
      }
    }
    
    // 404 最后匹配
    class UnknownPage extends StatelessWidget {
      const UnknownPage({Key? key}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('404'),
          ),
          body: const Center(
            child: Text('404', style: TextStyle(color: Colors.amber, fontSize: 40)),
          ),
        );
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
最后更新时间: 2022/11/27 15:07:42