在Flutter中,路由管理主要有两个类:Route和Navigator
RouteRoute:一个页面要想被路由统一管理,必须包装为一个Route。
但是Route是一个抽象类,所以它是不能被实例化的,实际开发中使用的是MaterialPageRoute,MaterialPageRoute并不是Route的直接子类。
MaterialPageRoute -> PageRoute -> ModalRoute -> TransitionRoute -> OverlayRoute -> Route
MaterialPageRoute在不同的平台有不同的表现:
在Android平台,打开一个页面会从屏幕底部滑动到屏幕的顶部,关闭页面时从顶部滑动到底部消失在iOS平台,打开一个页面会从屏幕右侧滑动到屏幕的左侧,关闭页面时从左侧滑动到右侧消失。当然,iOS平台我们也可以使用CupertinoPageRoute NavigatorNavigator:管理所有的Route的Widget,通过一个Stack来进行管理的
开发中无需手动去创建Navigator,因为开发中使用的MaterialApp、CupertinoApp、WidgetsApp默认有Navigator,直接使用即可
基本使用方法:
Navigator.push(context, route);
Navigator.pushNamed(context, routeName);
Navigator.pop(context);
1.路由基本使用
1.1 基本跳转
创建首页页面,中间添加一个按钮,点击按钮跳转到详情页面创建详情页面,中间添加一个按钮,点击按钮返回到首页页面
//按钮点击执行的代码
void _jumpToNextPage(BuildContext context){
Navigator.of(context).push(MaterialPageRoute(builder: (ctx){
return MaterialsPutInPage();
}));
}
//按钮点击执行的代码
void goBack(){
Navigator.of(context).pop();
}
1.2 参数传递
首页跳到详情页,携带一条信息’a home message’详情页返回首页,携带一条信息’a detail message’
首页核心代码:
在页面跳转时,会返回一个Future该Future会在详情页面调用pop时,回调对应的then函数,并且会携带结果 //首页按钮点击执行的代码
void _jumpToNextPage(BuildContext context){
//1.跳转代码
final future = Navigator.of(context).push(MaterialPageRoute(builder: (ctx){
return MaterialsPutInPage("a home message");
}));
//2.获取结果
future.then((value) => print(value));
}
//详情页接收数据
final String message;
MaterialsPutInPage(this.message);
//详情页按钮点击执行的代码
void goBack(){
Navigator.of(context).pop("a detail message");
}
2.命名路由
2.1 基本使用
我们可以通过创建一个新的Route,使用Navigator来导航到一个新的页面,但是如果在应用中很多地方都需要导航到同一个页面,那么就会存在很多重复的代码。
在这种情况下,我们可以使用命名路由(named route)
命名路由是将名字和路由的映射关系,在一个地方进行统一的管理有了命名路由,我们可以通过Navigator.pushNamed()方法来跳转到新的页面命名路由在哪里管理呢?可以放在MaterialApp的initialRoute和routes中
initialRoute:设置应用程序从哪一个路由开始启动,设置了该属性,就不需要再设置home属性了routes:定义名称和路由之间的映射关系,类型为Map修改MaterialApp中的代码
return MaterialApp(
title: Strings.home_title,
theme: ThemeData(
primaryColor: Colors.red
),
routes: {
"/" : (ctx)=> HomePage(),
"/material" : (ctx) => MaterialsPutInPage(),
},
//home: HomePage(),
initialRoute: "/",
);
修改跳转的代码
void _jumpToNextPage(BuildContext context){
// Navigator.of(context).push(MaterialPageRoute(builder: (ctx){
// return MaterialsPutInPage();
// }));
Navigator.of(context).pushNamed("/material");
}
2.2 命名规范化
在开发中,为了让每个页面对应的routeName统一,我们通常会在每个页面中定义一个路由的常量来使用
class AboutPage extends StatelessWidget {
static const String routeName = "/about";
@override
Widget build(BuildContext context) {
return Container();
}
}
class MaterialsPutInPage extends StatefulWidget {
static const String routeName = "/materials/putin";
@override
_MaterialsPutInPageState createState() => _MaterialsPutInPageState();
}
修改MaterialApp中routes的key
return MaterialApp(
title: Strings.home_title,
theme: ThemeData(
primaryColor: Colors.red
),
routes: {
HomePage.routeName : (ctx)=> HomePage(),
MaterialsPutInPage.routeName : (ctx) => MaterialsPutInPage(),
AboutPage.routeName : (ctx) => AboutPage()
},
//home: HomePage(),
initialRoute: HomePage.routeName,
);
修改跳转代码
Navigator.of(context).pushNamed(MaterialsPutInPage.routeName);
2.3 参数传递
pushName时,传递参数
Navigator.of(context).pushNamed(MaterialsPutInPage.routeName,arguments: "a home message");
详情页中获取参数
在build方法中ModalRoute.of(context)可以获取到传递的参数
//1.获取数据
final message = ModalRoute.of(context).settings.arguments;
接收返回值
void _jumpToNextPage(BuildContext context){
//1.跳转代码
var future = Navigator.of(context).pushNamed(MaterialsPutInPage.routeName,arguments: "a home message");
//2.获取结果
future.then((value) => print(value));
}
//返回时传递参数
Navigator.of(context).pop("返回值");
2.4 路由钩子
2.4.1 onGenerateRoute
假设我们有一个页面AboutPage,也希望在跳转时,传入对应的参数message,并且已经有一个对应的构造方法
AboutPage代码
class HYAboutPage extends StatelessWidget {
staticconstString routeName = "/about";
finalString message;
HYAboutPage(this.message);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("关于页面"),
),
body: Center(
child: Text(message, style: TextStyle(fontSize: 30, color: Colors.red),),
),
);
}
}
首页跳转代码
RaisedButton(
child: Text("打开关于页"),
onPressed: () {
Navigator.of(context).pushNamed(HYAboutPage.routeName, arguments: "a home message");
},
)
此时如果继续使用routes中的映射关系,就不好进行配置了,因为AboutPage要求必须传入一个参数
这个时候我们可以使用onGenerateRoute的钩子函数:
onGenerateRoute: (settings) {
if (settings.name == "/about") {
return MaterialPageRoute(
builder: (ctx) {
return HYAboutPage(settings.arguments);
}
);
}
returnnull;
},
2.4.2 onUnknownRoute
如果我们打开的一个路由名称是根本不存在的,这个时候我们希望跳转到一个统一的错误页面。
如果没有进行特殊的处理,那么Flutter会报错RaisedButton(
child: Text("打开未知页面"),
onPressed: () {
Navigator.of(context).pushNamed("/abc");
},
)
创建错误跳转页面
class UnknownPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("错误页面"),
),
body: Container(
child: Center(
child: Text("页面跳转错误"),
),
),
);
}
}
设置onUnknownRoute
onUnknownRoute: (settings) {
return MaterialPageRoute(
builder: (ctx) {
return UnknownPage();
}
);
},
2.5 其它路由跳转
Navigator.of(context).pop();
Navigator.of(context).popAndPushNamed(routeName);
Navigator.of(context).popUntil((route) => false);
Navigator.of(context).pushNamed(routeName);
Navigator.of(context).pushReplacementNamed(routeName);
Navigator.of(context).pushNamedAndRemoveUntil(newRouteName, (route) => false);
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)