路由:核心是 路由映射表
.
如:名字 detail
映射到 DetailPage
页面等
在Flutter中,路由管理主要有两个类:Route和Navigator.
Route
一个页面要想被路由统一管理,必须包装为一个Route
Navigator
管理所有的Route的Widget,通过一个Stack来进行管理.
MaterialApp、CupertinoApp、WidgetsApp它们默认是有插入Navigator的,在需要的时候,只需要直接使用即可.Navigator.of(context)
Navigator常用方法:
// 路由跳转:传入一个路由对象
Future push(Route route)
// 路由跳转:传入一个名称(命名路由)
Future pushNamed(
String routeName, {
Object arguments,
})
// 路由返回:可以传入一个参数
bool pop([ T result ])
命名路由
- 命名路由是将名字和路由的映射关系,在一个地方进行统一的管理
- 有了命名路由,就可以通过
Navigator.pushNamed()
方法来跳转到新的页面
命名路由的位置
放在MaterialApp的 initialRoute 和 routes 中
initialRoute
:设置应用程序从哪一个路由开始启动,设置了该属性,就不需要再设置home属性了routes
:定义名称和路由之间的映射关系,类型为Map
onGenerateRoute
: 通过pushNamed进行跳转,但是对应的name没有在routes中有映射关系,那么就会执行onGenerateRoute
钩子函数 . 另外,onGenerateRoute
也可以作为页面跳转的权限控制.;onUnknownRoute
: 如果打开的一个路由名称是根本不存在的,这个时候可以跳转到一个统一的错误页面。
打开命名路由时,如果指定的路由名在路由表中已注册,则会调用路由表中的builder函数来生成路由组件;如果路由表中没有注册,才会调用onGenerateRoute来生成路由。
完整代码
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue, splashColor: Colors.transparent),
initialRoute: "/",
routes: {
"/": (context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
// "/home": (ctx) => HomePage(),
"/detail": (ctx) => DetailPage()
},
onGenerateRoute: (settings) { //路由钩子 . 手动创建对应的Route进行返回;
if (settings.name == "/about") { //settings.name: 跳转的路径名称
return MaterialPageRoute(builder: (ctx) {
return AboutPage(settings.arguments); //settings.arguments:跳转时携带的参数
});
}
return null;
},
onUnknownRoute: (settings) {
return MaterialPageRoute(builder: (ctx) {
return UnknownPage();
});
},
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
// final message = ModalRoute.of(context).settings.arguments;
var _message = '';
_onPushTop(BuildContext context) {
final future = Navigator.of(context)
.pushNamed('/detail', arguments: "a home message of naned route"); //主动跳转时arguments传递参数
// 2.获取结果
future.then((res) {
setState(() {
_message = res;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'显示结果: ' + _message,
),
FlatButton(
child: Text("跳转下一页", style: TextStyle(color: Colors.black)),
onPressed: () => _onPushTop(context),
),
RaisedButton(
child: Text("打开关于页"),
onPressed: () {
Navigator.of(context).pushNamed(AboutPage.routeName,
arguments: "a home message");
},
),
RaisedButton(
child: Text("打开未知页面"),
onPressed: () {
Navigator.of(context).pushNamed("/abc");
},
),
],
),
),
);
}
}
class DetailPage extends StatelessWidget {
// 按钮点击执行的代码
_onBackTap(BuildContext context) {
Navigator.of(context).pop("a detail message");
}
@override
Widget build(BuildContext context) {
//接收上级页面传过来的参数
final message = ModalRoute.of(context).settings.arguments;
return new Scaffold(
appBar: new AppBar(
title: Text('这是第二页'),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop("a back detail message"); //pop跳转时直接放入参数
},
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'首页带来的内容: ' + message,
),
// child:
RaisedButton(
child: Text("返回首页"),
onPressed: () => _onBackTap(context),
),
]),
),
);
}
}
class AboutPage extends StatelessWidget {
static const String routeName = "/about";
final String message;
AboutPage(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),
),
),
);
}
}
class UnknownPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("错误页面"),
),
body: Container(
child: Center(
child: Text("页面跳转错误"),
),
),
);
}
}