1. 简单的路由使用:
// 跳转到一个新的页面
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return HomePage();
}));
MaterialPageRoute
继承自PageRoute
(抽象类),MaterialPageRoute
是Material
组件库提供的组件,它可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画。
构造函数:
MaterialPageRoute({
// 构建路由页面,返回一个widget
WidgetBuilder builder,
// 包含路由的配置信息,如路由名称、是否初始路由(首页)
RouteSettings settings,
// 默认情况下,入栈一个新路由时,原来的路由一直保存,如果想在路由没用的时候(??)释放其资源,设置maintainState为false
bool maintainState = true,
// 表示新的路由页面是否是一个全屏的模态对话框,ios中如果为true,说明是模态跳转
bool fullscreenDialog = false,
})
可以继承PageRoute来实现自定义路由切换动画。
2. Navigator
使用栈管理路由。
2.1 基础用法:打开&关闭
// 打开新的页面,返回一个Future对象,接收新路由出栈(关闭)时的返回数据
Future push(BuildContext context, Route route)
// 关闭页面,result为返回参数
bool pop(BuildContext context, [ result ])
Navigator
类中第一个参数为context
的静态方法都对应一个实例方法,比如:Navigator.push(BuildContext context, Route route)
等价于 Navigator.of(context).push(Route route)
。
2.2 逆向传值
场景:A页面中打开B页面,B页面关闭时给A传值。
代码如下:
A页面跳转代码:
// 返回的是一个Future对象
Future future = Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return HomePage();
},
maintainState: false),
);
// 获取回调过来的数据
future.then((value) {
print(value);
});
B页面代码:
// 关闭页面
Navigator.of(context).pop("这是回调给A页面的数据");
2.3 命名路由
就是给路由起个名字
,然后使用名字打开路由,更简单方便。
2.3.1 路由表
维护路由和名字的映射关系,就需要用到路由表
:
// value 是一个builder回调函数,用于生成相应的路由widget
Map<String, WidgetBuilder> routes;
通过路由名字打开路由时,会从路由表中查找对应的WidgetBuilder回调函数
,然后调用该回调函数生成路由Widget
并返回。
2.3.2 路由表注册
在main.dart
文件中的MaterialApp构造函数
中,添加routes
(注册路由表)和initialRoute
(标明应用的首页):
MaterialApp(
title: 'FlutterStudy',
initialRoute:"/", //名为"/"的路由作为应用的home(首页)
theme: ThemeData(
primarySwatch: Colors.blue,
),
//注册路由表
routes:{
"login_page": (context) => LoginPage(),
"/":(context) => HomePage(), //注册首页路由
} ,
);
如果使用了
initialRoute
指定应用首页,那么MaterialApp
就不能使用home
属性指定首页了,会有冲突。
2.3.3 命名路由简单使用
命名路由和普通路由的方法不同在于方法名字多了一个 named以及参数不同
,很好区分,比如下面的方法:
- 通过路由名打开新路由
Future pushNamed(BuildContext context, String routeName,{Object arguments})
示例:
// 通过路由名字打开路由,并传递参数
Navigator.of(context)
.pushNamed("login_page", arguments: {"id": "111"});
// 接收参数
routes: {
"/": (context) => HomePage(),
"login_page": (context) {
// 获取参数
Map args = ModalRoute.of(context).settings.arguments;
print(args);
return LoginPage(id: args['id']);
}
},
}
2.3.4 路由生成钩子
使用场景:APP中打开某些功能需要判断是否登录,通过路由生成钩子可以统一进行处理。
MaterialApp
有一个onGenerateRoute
属性,当通过Navigator.pushName()
打开路由时:
- 如果指定的路由名
已经在路由表中注册
了,就会调用路由表中的builder函数
生成路由组件; - 如果没有注册,会调用
onGenerateRoute
来生成路由;
onGenerateRoute 只会对命名路由生效。
回调签名:
Route<dynamic> Function(RouteSettings settings)
可以不使用路由表,只使用onGenerateRoute
回调,然后在该回调中进行统一的权限控制:
MaterialApp(
... //省略无关代码
onGenerateRoute:(RouteSettings settings){
return MaterialPageRoute(builder: (context){
String routeName = settings.name;
// 如果访问的路由页需要登录,但当前未登录,则直接返回登录页路由,
// 引导用户登录;其它情况则正常打开路由。
}
);
}
);
3. Navigator相关方法记录
3.1 常用跳转方法:
// 弹出当前页面,并跳转到一个新的页面
// A->B->C->D ,D页面调用后,A->B->C->B
Navigator.popAndPushNamed(context, 'B');
// 弹出栈中的页面,直到指定的页面
// A->B->C->D ,D页面调用后,A->B
Navigator.popUntil(context, ModalRoute.withName("B"));
// 弹出栈中的页面,直到指定的页面,然后跳转一个新页面
// A->B->C->D ,D页面调用后,A->B->F
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => new F()),
ModalRoute.withName("B"));
// 和上面一样,只不过是跳转命名路由
// A->B->C->D ,D页面调用后,A->B->F
Navigator.pushNameAndRemoveUntil(
context,
"F"
ModalRoute.withName("B"));
// 和上面一样,只不过是跳转命名路由
// A->B->C ,D页面调用后,A->B->D
Navigator.pushReplacementNamed(context, "D");
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (BuildContext context) => new D()));
3.2 其他方法:
// 判断是否可以导航到新页面
canPop
// 可能会导航到新页面
maybePop
// 从Navigator中删除路由,同时执行Route.dispose操作。
removeRoute
// 从Navigator中删除路由,同时执行Route.dispose操作,要替换的路由是传入参数anchorRouter里面的路由。
removeRouteBelow
// 将Navigator中的路由替换成一个新路由。
replace
// 将Navigator中的路由替换成一个新路由,要替换的路由是是传入参数anchorRouter里面的路由
replaceRouteBelow
项目中使用时可以自己封装一下路由管理类,也可以使用 Fluro。本篇文章只是记录 Navigator 的一些用法,更详细的可以参考:Flutter实战:路由管理
网友评论