一、Flutter 页面跳转及参数传递
在Android中,可以通过Intents来在Activity之间切换或调用外部组件,但Flutter不具有Intents的概念,那么我们如何在Flutter中来实现屏幕切换呢?要在Flutter中切换屏幕,您可以访问路由以绘制新的Widget。 管理多个屏幕有两个核心概念和类:Route (路由)和 Navigator(导航器)。Route是应用程序的“屏幕”或“页面”的抽象(可以认为是Activity), Navigator是管理Route的Widget。Navigator可以通过push和pop route以实现页面切换。
Flutter和Android相似,Android中需要在AndroidManifest.xml中声明您的Activitie组件,在Flutter中,您可以将具有指定Route的Map传递到顶层MaterialApp,
首先我们看一下通过路由实现的页面切换效果图:
其中点击跳转到RouteA中是通过pushName跳转的,没有携带数据。点击跳转到RouteB中是通过push跳转的,并且携带了一个对象,然后在RouteB中接收显示,在RouteB中返回的时候也将处理结果返回,在StudyRoute中接收处理RouteB返回的处理结果。下面我们看一下这两种route具体实现过程:
1、MaterialApp中的routes声明如下:
return new MaterialApp(
theme: ThemeData(primarySwatch: Colors.blue),
routes: <String, WidgetBuilder>{
'/RouteA': (BuildContext context) {
return new RouteA();
},
'/RouteB': (BuildContext context) {
return new RouteB(product: new Product("测试", "我是描述"),);
},
},
...
);
2、通过Navigator指定跳转
- 通过pushNamed跳转页面,这种方式跳转的时候一般没法传递数据,但可以接收返回值。类似与Android的startActivityForResult
Navigator.pushNamed(context, '/RouteA').then((Object result) async {
print('======$result');
});
或者
Navigator.of(context).pushNamed('/RouteA').then((Object result){
print('======$result');
});
注意:通过pushNamed跳转的路由必须在MaterialApp的routes中声明路由跳转路径。
- 通过push的方式跳转页面,同时传递数据到下一个页面,并接收处理后的结果
Navigator.push<String>(context,
new MaterialPageRoute(builder: (BuildContext context) {
return new RouteB(product: _product,);
}),).then((String result){
print("===================$result");
});
3、实现案例目录
StudyRoute代码如下:
class StudyRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return new MaterialApp(
theme: ThemeData(primarySwatch: Colors.blue),
routes: <String, WidgetBuilder>{
'/RouteA': (BuildContext context) {
return new RouteA();
},
'/RouteB': (BuildContext context) {
return new RouteB(product: new Product("测试", "我是描述"),);
},
},
home: new Scaffold(
appBar: new AppBar(
title: new Text('Flutter Route使用'),
),
body: new Study(),
),
);
}
}
class Study extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
Product product = new Product("Intent在Flutter中等价于什么?", "在Android中,Intents主要有两种使用场景:在Activity之间切换,以及调用外部组件。 Flutter不具有Intents的概念,但如果需要的话,Flutter可以通过Native整合来触发Intents。要在Flutter中切换屏幕,您可以访问路由以绘制新的Widget。 管理多个屏幕有两个核心概念和类:Route 和 Navigator。Route是应用程序的“屏幕”或“页面”的抽象(可以认为是Activity), Navigator是管理Route的Widget。Navigator可以通过push和pop route以实现页面切换。和Android相似,您可以在AndroidManifest.xml中声明您的Activities,在Flutter中,您可以将具有指定Route的Map传递到顶层MaterialApp实例");
return _StudyState(product);
}
}
class _StudyState extends State<Study> {
final Product _product;
_StudyState(this._product);
void _onTapA() {
Navigator.pushNamed(context, '/RouteA');
Navigator.of(context).pushNamed('/RouteA');
}
void _onTapB() {
Navigator.push<String>(context,
new MaterialPageRoute(builder: (BuildContext context) {
return new RouteB(product: _product,);
}),).then((String result){
print("===================$result");
//Fluttertoast.showToast(msg: result);
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Center(
child: new Container(
width: 300,
height: 300,
//color: Colors.blueAccent,
child: new Column(
children: <Widget>[
new Expanded(
flex: 1,
child: new Container(
width: 300,
//color: Colors.red,
decoration: BoxDecoration(shape: BoxShape.circle,color: Colors.red),
child: new InkWell(
onTap: _onTapA,
child: new Center(
child: new Text('跳转到Route A'),
)
),
),
),
new Expanded(
flex: 1,
child: new Container(
width: 300,
decoration: BoxDecoration(shape: BoxShape.circle,color: Colors.green),
child: new InkWell(
onTap: _onTapB,
child: new Center(
child: new Text('跳转到Route B',textAlign: TextAlign.center),
)
),
),
),
],
),
),
);
}
}
通过pushName跳转到RouteA,并且通过pop返回到StudyRoute页面。
class RouteA extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
//automaticallyImplyLeading: false关闭返回的部件
appBar: new AppBar(
title: new Text('我是Route A'),
leading: Builder(builder: (BuildContext context) {
return new IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context, "携带的参数");
});
}),
),
body: new Container(
child: new Center(
child: new Text('Route A 页面显示'),
)
),
);
}
}
在RouteB中接收StudyRoute传递过来的参数并显示,同时用户点击返回的时候将返回结果回传给StudyRoute
class RouteB extends StatelessWidget{
final Product product;
const RouteB({Key key, @required this.product}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
appBar: new AppBar(
title: new Text('Flutter RouteB'),
leading: Builder(builder: (BuildContext context){
return new IconButton(icon: Icon(Icons.arrow_back_ios), onPressed:(){
Navigator.pop(context,"我是返回的数据");
});
}),
),
body: new Center(
child: new Column(
children: <Widget>[
new Text(product.title,style: TextStyle(color: Color(0xFF333333),fontSize: 18,fontWeight: FontWeight.bold),),
new Text(product.description,softWrap: true,),
],
),
),
);
}
}