Flutter使用Navigator和Routes来管理页面导航,相应的,在iOS中有push/pop和‘present/dismiss’等方式。一个路由是App中‘屏幕’或‘页面’的抽象,一个Navigator是管理多个路由的Widget,它的工作原理与iOS中的UINavigationController相似。
在页面之间跳转可以有以下选择:
- 具体制定一个有路由名构成的Map。(MaterailApp)
- 直接跳转到一个路由。(WidgetApp)
构建Map:
1
2
3
4
5
6
7
8
9
10
void main() {
runApp(MaterialApp(
home: MyAppHome(), // becomes the route named '/'
routes: <String, WidgetBuilder> {
'/a': (BuildContext context) => MyPage(title: 'page A'),
'/b': (BuildContext context) => MyPage(title: 'page B'),
'/c': (BuildContext context) => MyPage(title: 'page C'),
},
));
}
通过路由名字,实现跳转(push):
1
Navigator.of(context).pushNamed('/b');
自定义路由:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Navigator.push(context, PageRouteBuilder(
opaque: false,
pageBuilder: (BuildContext context, _, __){
return Center(child: Text('My Page Route'));
},
transitionsBuilder: (__, Animation<double> animation, ____, Widget child) {
return FadeTransition(
opacity: animation,
child: RotationTransition(
turns: Tween<double>(begin: 0.5, end: 1.0).animate(animation),
child: child,
),
);
}
));
页面路径由两部分构成,“页面”和“转场”(transition)。该页面成为传递给该transitionsBuilder函数的子代的后代。通常情况下,该页面仅内置一次,因为它不依赖于它的动画参数(在这个例子中_ ,__是省略的参数)。过渡是基于持续过程的每一帧。
使用Navigator类还可以用来获取push到栈中的路由返回的结果,通过await等待路由返回的结果,或者使用then()方法来获取:
1
2
3
4
5
6
Map coordinates = await Navigator.of(context).pushNamed('/c');
// 或者
// Navigator.of(context).pushNamed('/c').then((data){
// print('then=$data');
// });
注意,此处使用了await,该函数应该添加async关键字。
在 location 路由中,一旦用户选择了地点,携带结果一起 pop() 出栈:
1
Navigator.of(context).pop({"lat":43.821757,"long":-79.226392});
导航示例:
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
class NavigationSampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: 'Navigation',
theme: ThemeData(
primarySwatch: Colors.red
),
home: NavigationSampleAppPage(title: 'Home Page',),
routes: <String, WidgetBuilder> {
'/a': (BuildContext context) => NavigationSampleAppPage(title: 'Home Page'),
'/b': (BuildContext context) => NavigationSampleAppPage(title: 'page two'),
'/c': (BuildContext context) => NavigationSampleAppPage(title: 'page three'),
},
);
}
}
class NavigationSampleAppPage extends StatefulWidget {
final String title;
NavigationSampleAppPage({Key key, this.title}) : super(key: key);
_NavigationSampleAppPageState createState() => _NavigationSampleAppPageState(title);
}
class _NavigationSampleAppPageState extends State<NavigationSampleAppPage> {
final String title;
_NavigationSampleAppPageState(this.title);
Future _push() async {
var result;
if (this.title.contains('Home')) {
Navigator.of(context).pushNamed('/b');
} else if (this.title.contains('two')) {
// 带返回值,方式一
Navigator.of(context).pushNamed('/c').then((data){
print('then=$data');
});
// 带返回值方式二
// result = await Navigator.of(context).pushNamed('/c');
} else if (this.title.contains('three')) {
// 返回page one
Navigator.of(context).popUntil(ModalRoute.withName('/b'));
// 带返回值
// Navigator.of(context).pop({'key': 'value'});
}
print('result = $result');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
actions: <Widget>[
IconButton(
icon: Icon(Icons.favorite),
onPressed: _push,
)
],
),
);
}
}
跳转第三方APP
在iOS中,使用URL Scheme方式。在Flutter中,可以创建一个原省平台的整合层,或者使用现有插件,例如:url_launcher