路由 Navigator
Smoothness 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