Flutter路由(Navigator)的使用
Push类型方法将给定的路由入栈(即打开新的页面),返回值是一个Future对象,用以接收新路由出栈(即关闭)时的返回数据
Push方法:
/**
* 在栈顶入栈一个新的路由
* route 路由页面
*/
push(Route route)
/**
* 将当前路由替换为一个新的路由
* newRoute 同上route
* result 可选参数result表示的是这个页面的返回结果,如果设置的话,会返回给被替换的这个页面的前一个页面
*/
pushReplacement(Route newRoute, { TO? result })
/**
* 跳转到指定页面,并按顺序(从栈顶到栈底)移出之前的所有页面,直到predicate返回true。
* newRoute 同上route
* predicate 类型RoutePredicate = bool Function(Route<dynamic> route)
* route获取路由信息路由信息,确定移除指定路由返回true。返回false,移出之前的所有页面。
*/
pushAndRemoveUntil(Route newRoute, RoutePredicate predicate)
Route分为了页面路由(PageRoute)和窗口路由(PopupRoute)。PopupRoute的默认实现均为私有,要用到的话需要我们自己去实现。PageRoute默认提供了三个公开的实现类:
- CupertinoPageRoute:Cupertino风格的默认实现。
- MaterialPageRoute:Material风格的默认实现。
- PageRouteBuilder:自定义PageRoute,比如一些动画效果。
PageRouteBuilder 使用
/**
* settings 包含路由的配置信息,如路由名称、是否初始路由
* pageBuilder 用来构建路由的主要内容
* transitionsBuilder 用于构建路由的变换效果
* transitionDuration 变换效果的持续时间
* opaque 是否不透明,默认为true,如果是不透明的话,路由变换完成之后,不会再构建位于该路由之下的路由,以节省资源
* barrierDismissible 点击屏障是否自动消失。
* barrierColor 模态屏障的颜色。如果为null,则屏障将是透明的。比如弹出一个对话框时,背景可以设置成灰暗的。注意Dialog也是一个路由。
* barrierLabel
* maintainState 默认情况下,当入栈一个新路由时,原来的路由仍然会被保存在内存中,如果想在路由没用的时候释放其所占用的所有资源,可以设置`maintainState`为 `false`
*/
PageRouteBuilder({
RouteSettings settings,
@required this.pageBuilder,
this.transitionsBuilder = _defaultTransitionsBuilder,
this.transitionDuration = const Duration(milliseconds: 300),
this.opaque = true,
this.barrierDismissible = false,
this.barrierColor,
this.barrierLabel,
this.maintainState = true,
}) : assert(pageBuilder != null),
assert(transitionsBuilder != null),
assert(barrierDismissible != null),
assert(maintainState != null),
assert(opaque != null),
super(settings: settings);
例如:
PageRouteBuilder(
transitionDuration: Duration(milliseconds: 500), //动画时间为500毫秒
pageBuilder: (BuildContext context, Animation animation,
Animation secondaryAnimation) {
return FadeTransition(
//使用渐隐渐入过渡,
opacity: animation,
child: PageB(), //路由B
);
},
)
PushName方法
/**
* 在栈顶入栈一个新的路由
* routeName 路由名字
* arguments 传递的参数
*/
pushNamed(String routeName, { Object? arguments})
/**
* 将当前路由替换为一个新的路由
* routeName 同上routeName
* result 可选参数result表示的是这个页面的返回结果,如果设置的话,会返回给被替换的这个页面的前一个页面
* arguments 传递的参数
*/
pushReplacementNamed( String routeName, {TO? result,
Object? arguments})
/**
* 跳转到指定页面,并按顺序(从栈顶到栈底)移出之前的所有页面,直到predicate返回true。
* newRouteName 同上route
* predicate 类型RoutePredicate = bool Function(Route<dynamic> route)
* route获取路由信息路由信息,确定移除指定路由返回true。返回false,移出之前的所有页面。
* arguments 传递的参数
*/
pushNamedAndRemoveUntil( String newRouteName,
RoutePredicate predicate, {
Object? arguments,
})
注意: 使用命名路由跳转,首先需要将路由进行注册
class MainPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Good'),
routes: {
"mainPage": (context) => MainPage(),
"loginPage": (context) => LoginPage()
},
);
}
}
获取传递的数据
路由跳转新界面使用arguments传递数据或者使用PageRouteBuilder中的settings传递数据。
使用 ModalRoute.of(context).settings.arguments 获取数据。
路由拦截器(路由钩子)
通过onGenerateRoute做一些全局的路由跳转前置处理逻辑。在MaterialApp中使用onGenerateRoute参数设置拦截器。
代码:
MaterialApp(
... //省略无关代码
onGenerateRoute:(RouteSettings settings){
return MaterialPageRoute(builder: (context){
String routeName = settings.name;
// 如果访问的路由页需要登录,但当前未登录,则直接返回登录页路由,
// 引导用户登录;其他情况则正常打开路由。
}
);
}
);
pop方法
/**
* 当前路由出栈
* result 可选参数,返回数据
*/
pop([ T result ])
/**
* 当前路由出栈,入栈一个新路由
* routeName 同上routeName
* result 可选参数result表示的是这个页面的返回结果,如果设置的话,会返回给被替换的这个页面的前一个页面
* arguments 传递的参数
*/
popAndPushNamed(String routeName, {
TO? result,
Object? arguments})
/**
* 从栈顶开始,逐个pop,直到参数中指定的路由为止
* result 可选参数,返回数据
*/
popUntil
/**
* 判断当前路由是否可以出栈,如果栈内只有当前路由,返回false,如果当前路由前面还有路由,返回true。也就是说栈底的路由,该方法返回false
*/
canPop(BuildContext context)
/**
* 当前路由如能能出栈就出栈,如果不能就什么都不做。
* 是pop的安全返回方式.参数作用于pop的一样
* result 可选参数,返回数据
*/
maybePop(BuildContext context, [ T result ])
remove方法
/**
*删除一个指定的路由,如果该路由存在于栈内正常删除,否则报错,例如:路由顺序A-B-C-D,remove C,结果路由顺序是A-B-D
*route 需要移除的路由
*/
removeRoute(BuildContext context, Route route)
/**
*给定一个路由,在路由表内删除其前一个路由。例如:路由顺序A-B-C-D,remove C,结果路由顺序是A-C-D
*anchorRoute 需要移除的路由
*/
removeRouteBelow(BuildContext context, Route anchorRoute)
replace方法
/**
* 用一个新的路由,将路由表内的一个已存在的路由替换掉
* oldRoute 需要替换的路由
* newRoute 新路由
*/
replace(BuildContext context, { @required Route oldRoute, @required Route newRoute })
/**
* 用一个新的路由,将路由表内的一个已存在的路由的前面的路由给替换掉
* anchorRoute 需要替换的后一个路由
* newRoute 新路由
*/
replaceRouteBelow(BuildContext context, { @required Route anchorRoute, Route newRoute })