参考练习:https://book.flutterchina.club/chapter2/flutter_router.html
路由(Route)在移动开发中通常指页面(Page),这跟web开发中单页应用的Route概念意义是相同的,Route在Android中通常指一个Activity,在iOS中指一个ViewController。所谓路由管理,就是管理页面之间如何跳转,通常也可被称为导航管理。这和原生开发类似,无论是Android还是iOS,导航管理都会维护一个路由栈,路由入栈(push)操作对应打开一个新页面,路由出栈(pop)操作对应页面关闭操作,而路由管理主要是指如何来管理路由栈。
我们VS Code创建Flutter应用时,默认的是一个计数器的例子,“计数器”示例的基础上,做如下修改:
flutter中的默认导航分成两种,一种是构建路由,一种是命名的路由。
构建路由
- 创建一个新路由,命名“NewRoute”
class NewRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("New route"),
),
body: Center(
child: Text("This is new route"),
),
);
}
}
新路由继承自StatelessWidget,界面很简单,在页面中间显示一句"This is new route"。
- 在_MyHomePageState.build方法中的Column的子widget中添加一个按钮(FlatButton) :
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
... //省略无关代码
FlatButton(
child: Text("open new route"),
textColor: Colors.blue,
onPressed: () {
//导航到新路由
Navigator.push( context,
new MaterialPageRoute(builder: (context) {
return new NewRoute();
}));
},
),
],
)
我们添加了一个打开新路由的按钮,并将按钮文字颜色设置为蓝色,点击该按钮后就会打开新的路由页面。
命名路由
所谓命名路由(Named Route)即给路由起一个名字,然后可以通过路由名字直接打开新的路由。这为路由管理带来了一种直观、简单的方式。
- 注册路由表
我们需要先注册路由表后,我们的Flutter应用才能正确处理命名路由的跳转。注册方式很简单,我们回到之前“计数器”的示例,然后在MyApp类的build方法中找到MaterialApp,添加routes属性,代码如下:
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
//注册路由表
routes:{
"new_page":(context)=>NewRoute(),
} ,
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
- 通过路由名打开新路由页
接下来我们通过路由名来打开新的路由页,修改FlatButton的onPressed回调代码,改为
onPressed: () {
Navigator.pushNamed(context, "new_page");
//Navigator.push(context,
// new MaterialPageRoute(builder: (context) {
// return new NewRoute();
//}));
},
热重载应用,再次点击“open new route”按钮,依然可以打开新的路由页。
构建路由传参
- 创建一个新的路由FirstScreen.如下: 参数$userName
// 构建路由传参
class FirstScreen extends StatelessWidget {
final String userName;
const FirstScreen({Key key, this.userName}) : super(key: key);
@override
Widget build(BuildContext context) {
// 获取路由参数
print("路由传递过来的参数--- $userName");
return Scaffold(
appBar: AppBar(
title: Text("FirstScreen"),
),
body: Center(
child: Text("This is First Screen"),
),
);
}
}
- 在打开路由时传递参数
//导航到新路由
Navigator.push( context,
new MaterialPageRoute(builder: (context) {
return new FirstScreen(userName:"Li peng");
}));
- 热重载结果
flutter: 路由传递过来的参数--- Li peng
命名路由传参
- 在路由页通过RouteSetting对象获取路由参数
class NewRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
//获取路由参数
var args=ModalRoute.of(context).settings.arguments;
print("路由传递过来的参数--- $args");
return Scaffold(
appBar: AppBar(
title: Text("New route"),
),
body: Center(
child: Text("This is new route"),
),
);
}
}
- 在打开路由时传递参数
Navigator.of(context).pushNamed("new_page", arguments: "hi");
- 热重载结果
Performing hot reload... ⣽flutter: 路由传递过来的参数--- hi
这样两种传参都实现了!!! 但以上是由前先后传参的!
Navigator.pop 返回页面并传参
- 我们根据上面 构建路由传参的例子 : FirstScreen 路由修改来实现Navigator.pop 返回页面并传参:
在FirstScreen 页面增加一个按钮,用于出发 Navigator.pop 返回
// 构建路由传参
class FirstScreen extends StatelessWidget {
final String userName;
const FirstScreen({Key key, this.userName}) : super(key: key);
@override
Widget build(BuildContext context) {
// 获取路由参数
print("路由传递过来的参数--- $userName");
return Scaffold(
appBar: AppBar(
title: Text("FirstScreen"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("This is First Screen"),
FlatButton(
child: Text("open new route"),
textColor: Colors.blue,
onPressed: () {
// 返回传参
Navigator.pop(context, "我是回传参数,我带回了点好吃的给大家!!!");
})
],
),
),
);
}
}
- 在Navigator.push 的地方接受回传参数
//导航到新路由
Navigator.push<String>(context, new MaterialPageRoute(builder: (BuildContext context){
return new FirstScreen(userName:"请输入昵称");
})).then( (String result){
//处理代码
print("返回的回调---$result");
});
- 热重载结果
Performing hot reload...
Reloaded 1 of 440 libraries in 158ms.
flutter: 路由传递过来的参数--- 请输入昵称
flutter: 返回的回调---我是回传参数,我带回了点好吃的给大家!!!
总结:实现了页面路由的跳转、从前向后传参、从后往前传参。