-
Route:路由是应用程序页面的抽象,对应 Android 中 Activity 和 iOS 中的 ViewController,由 Navigator 管理。
-
Navigator:Navigator 是一个组件,管理和维护一个基于堆栈的历史记录,通过 push 和 pop 进行页面的跳转。
push 和 pop
class APage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,child: RaisedButton(
child: Text('A 页面'),onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return BPage();
}));
},),);
}
}
class BPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,child: RaisedButton(
child: Text('B 页面'),onPressed: () {
},);
}
}
RaisedButton(
child: Text('B 页面'),onPressed: () {
Navigator.of(context).pop();
},)
RaisedButton(
child: Text('B 页面'),onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return APage();
}));
},)
- 试想如下场景,进入购物App,展示购物列表,点击其中一个进入商品详细页面,使用 push 再次进入购物列表,然后在进入商品详细页面...,如此反复,路由堆栈中将会存放大量的购物列表和商品详细页面的路由,点击返回按钮,会将反复显示购物列表和商品详细页面。
- 页面切换时路由动画 push 和 pop 是不同。
maybePop 和 canPop
RaisedButton(
child: Text('A 页面'),)
RaisedButton(
child: Text('A 页面'),onPressed: () {
Navigator.of(context).maybePop();
},)
RaisedButton(
child: Text('B 页面'),onPressed: () {
if(Navigator.of(context).canPop()){
Navigator.of(context).pop();
}
},)
pushNamed
MaterialApp(
title: 'Flutter Demo',routes: <String,WidgetBuilder>{
'/A': (context) => APage(),'/B': (context) => BPage(),},home: Scaffold(
body: APage(),)
RaisedButton(
child: Text('A 页面'),onPressed: () {
Navigator.of(context).pushNamed('/B');
},)
pushReplacementNamed 和 popAndPushNamed
RaisedButton(
child: Text('A 页面'),)
RaisedButton(
child: Text('B 页面'),onPressed: () {
Navigator.of(context).pushReplacementNamed('/C');
},)
RaisedButton(
child: Text('C 页面'),)
RaisedButton(
child: Text('B 页面'),onPressed: () {
Navigator.of(context).popAndPushNamed('/C');
},)
-
欢迎页面:应用程序打开后首先进入欢迎界面,然后进入首页,进入首页后不应该再进入欢迎界面。
-
登录页面:登录成功后进入相关页面,此时按返回按钮,不应再进入登录页面。
pushNamedAndRemoveUntil
RaisedButton(
child: Text('C 页面'),onPressed: () {
Navigator.of(context).pushNamedAndRemoveUntil('/D',ModalRoute.withName('/B'));
},
RaisedButton(
child: Text('D 页面'),)
Navigator.of(context).pushNamedAndRemoveUntil('/D',ModalRoute.withName('/B'));
Navigator.of(context).pushNamedAndRemoveUntil('/D',(Route route)=>false);
popUntil
RaisedButton(
child: Text('D 页面'),onPressed: () {
Navigator.of(context).popUntil(ModalRoute.withName('/A'));
},)
传递数据
class ProductDetail extends StatelessWidget {
final ProductInfo productInfo;
const ProductDetail({Key key,this.productInfo}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
}
Navigator.of(context).push(MaterialPageRoute(builder: (context){
return ProductDetail(productInfo: productInfo,);
}));
RaisedButton(
child: Text('A 页面'),onPressed: () {
Navigator.of(context).pushNamed('/B',arguments: '来自A');
},)
RaisedButton(
child: Text('${ModalRoute.of(context).settings.arguments}'),onPressed: () {
Navigator.of(context).pushNamed('/C');
},)
返回数据
RaisedButton(
child: Text('${ModalRoute.of(context).settings.arguments}'),onPressed: () {
Navigator.of(context).pop('从B返回');
},)
class APage extends StatefulWidget {
@override
_APageState createState() => _APageState();
}
class _APageState extends State<APage> {
String _string = 'A 页面';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,child: RaisedButton(
child: Text(_string),onPressed: () async {
var result =
await Navigator.of(context).pushNamed('/B',arguments: '来自A');
setState(() {
_string = result;
});
},);
}
}