大佬教程收集整理的这篇文章主要介绍了【Flutter 实战】路由堆栈详解,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
@L_489_0@r 路由管理中有两个非常重要的概念:
假设现在有2个页面 A 和 B,A中有一个按钮,点击跳转到 B 页面,A 页面代码:
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: () {
},);
}
}
当应用程序位于A页面时,路由堆栈中只有A,点击按钮跳转到B页面,路由堆栈中有 B 和 A,且 B 处于栈顶。
点击 B 页面的按钮返回到 A 页面,修改 B 页面按钮点击事件:
RaisedButton(
child: Text('B 页面'),onPressed: () {
Navigator.of(context).pop();
},)
路由堆栈的变化:
@H_673_66@
上面案例的效果是从 B 页面跳转到 A 页面,那是否也可以使用 push 方法?修改 B 页面按钮点击事件:
RaisedButton(
child: Text('B 页面'),onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return APage();
}));
},)
那是否可以使用 push 代替 pop 呢? 答案肯定是不可以的,
RaisedButton(
child: Text('A 页面'),)
在 A 页面时路由堆栈中只有 A,调用 pop 后,路由堆栈变化:
此时路由堆栈为空,没有可显示的页面,应用程序将会退出或者黑屏,好的用户体验不应如此,此时可以使用 maybePop,maybePop 只在路由堆栈有可弹出路由时才会弹出路由。
上面的案例在 A 页面执行maybePop:
RaisedButton(
child: Text('A 页面'),onPressed: () {
Navigator.of(context).maybePop();
},)
点击后不会出现弹出路由,因为当前路由堆栈中只有 A,在 B页面执行maybePop,将会返回到 A 页面。
也可以通过 canPop 判断当前是否可以 pop:
RaisedButton(
child: Text('B 页面'),onPressed: () {
if(Navigator.of(context).canPop()){
Navigator.of(context).pop();
}
},)
pushNamed 是命名路由的方式,需要在 MaterialApp 中配置路由名称:
@H_849_28@materialApp( title: '@L_489_0@r Demo',routes: <@R_874_10495@ng,WidgetBuilder>{ '/A': (context) => APage(),'/B': (context) => BPage(),},home: Scaffold( body: APage(),)
从 A 跳转到 B:
RaisedButton(
child: Text('A 页面'),onPressed: () {
Navigator.of(context).pushNamed('/B');
},)
@H_404_138@pushreplacementNamed 和 popAndPushNamed
有A、B、C 三个页面,A页面通过 pushNamed 跳转到 B:
RaisedButton(
child: Text('A 页面'),)
B 通过 pushreplacementNamed 跳转到 C:
RaisedButton(
child: Text('B 页面'),onPressed: () {
Navigator.of(context).pushreplacementNamed('/C');
},)
点击 C 页面按钮执行 pop:
RaisedButton(
child: Text('C 页面'),)
点击 C 页面按钮直接返回到了 A 页面,而不是 B 页面,因为 B 页面使用 pushreplacementNamed 跳转,路由堆栈变化:
B 页面跳转到 C 页面,使用 popAndPushNamed:
RaisedButton(
child: Text('B 页面'),onPressed: () {
Navigator.of(context).popAndPushNamed('/C');
},)
popAndPushNamed 路由堆栈和 pushreplacementNamed 是一样,唯一的区别就是 popAndPushNamed 有 B 页面退出动画。
popAndPushNamed 和 pushreplacementNamed 使当前页面不在路由堆栈中,所以通过 pop 无法返回此页面。
适用场景:
有如下场景,应用程序进入首页,点击登录进入登录页面,然后进入注册页面或者忘记密码页面...,登录成功后进入其他页面,此时不希望返回到登录相关页面,此场景可以使用 pushNamedAndRemoveUntil。
有A、B、C、D 四个页面,A 通过push进入 B 页面,B 通过push进入 C 页面,C 通过 pushNamedAndRemoveUntil 进入 D 页面同时删除路由堆栈中直到 /B 的路由,C 页面代码:
RaisedButton(
child: Text('C 页面'),onPressed: () {
Navigator.of(context).pushNamedAndRemoveUntil('/D',ModalRoute.withName('/B'));
},
D 页面按钮执行 pop:
RaisedButton(
child: Text('D 页面'),)
Navigator.of(context).pushNamedAndRemoveUntil('/D',ModalRoute.withName('/B'));
表示跳转到 D 页面,同时删除D 到 B 直接所有的路由,如果删除所有路由,只保存 D:
Navigator.of(context).pushNamedAndRemoveUntil('/D',(Route routE)=>falsE);
路由堆栈变化:
有如下场景,在入职新公司的时候,需要填写各种信息,这些信息分为不同部分,比如基本信息、工作信息、家庭信息等,这些不同模块在不同页面,填写信息时可以返回上一页,也可以取消,取消返回到首页,此场景可以使用 popUntil,一直 pop 到指定的页面。
有A、B、C、D 四个页面,D 页面通过 popUntil 一直返回到 A 页面,D 页面代码:
RaisedButton(
child: Text('D 页面'),onPressed: () {
Navigator.of(context).popUntil(ModalRoute.withName('/A'));
},)
路由堆栈变化:
有如下场景,商品列表页面,点击跳转到商品详情页面,商品详情页面需要商品的唯一id或者商品详情数据,有两种方式传递数据:
第一种:通过构造函数方式:
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,);
}));
此种方式无法用于命名路由的跳转方式。
第二种:通过命名路由设置参数的方式:
A 页面传递数据,
RaisedButton(
child: Text('A 页面'),onPressed: () {
Navigator.of(context).pushNamed('/B',arguments: '来自A');
},)
B 页面通过 @H_766_304@modalRoute.of(context).setTings.arguments 接收数据:
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返回');
},)
A 页面接收返回的数据:
class APage extends StatefulWidget {
@override
_APageState createState() => _APageState();
}
class _APageState extends State<APage> {
@R_874_10495@ng _@R_874_10495@ng = 'A 页面';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,child: RaisedButton(
child: Text(_@R_874_10495@ng),onPressed: () async {
var result =
await Navigator.of(context).pushNamed('/B',arguments: '来自A');
setState(() {
_@R_874_10495@ng = result;
});
},);
}
}
push 相关方法返回 Future 类型,使用 await 等待返回结果。
老孟@L_489_0@r博客(330个控件用法+实战入门系列文章):http://laomengit.com
欢迎加入@L_489_0@r交流群(微信:laomENGIt)、关注公众号【老孟@L_489_0@r】:
@H_616_356@ | |
---|---|
以上是大佬教程为你收集整理的【Flutter 实战】路由堆栈详解全部内容,希望文章能够帮你解决【Flutter 实战】路由堆栈详解所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。