Flutter之路由跳转(上)

一、基础知识

核心概念

RouteNavigator
1.route:应用程序页面的抽象
2.Navigator,是一个组件管理和维护基于堆栈的历史记录,使用pop和push跳转页面页面间的跳转。


Navigator如何管理携带值的路由跳转
Navigator是一个栈结构,通过push 和pop来操作。push加入一个Route,并将返回一个Future对象。Future push(BuildContext context, Route route) pop则将栈顶元素出栈。 bool pop(BuildContext context, [ result ])result为页面关闭时返回给上一个页面的数据。 命名的路由(Named Route)Navigator类中第一个参数为context的静态方法都对应一个Navigator的实例方法, 比如Navigator.push(BuildContext context, Route route)等价Navigator.of(context).push(Route route)很多情况下在路由跳转时我们需要带一些参数,比如打开商品详情页时,我们需要带一个商品id,这样商品详情页才知道展示哪个商品信息;又比如我们在填写订单时需要选择收货地址,打开地址选择页后,可以将用户选择的地址返回到订单页等等。非命名路由传值:通过Navigator.push(context,route)来传递。值传回:Navigator.pop(context,result),result就是要返回的值。

Navigator 继承自 StatefulWidget,它也是小组件,它有很多相关静态函数,可以帮我们达到页面跳转和数据交互的功能:
push 将设置的router信息推送到Navigator上,实现页面跳转。
of 主要是获取 Navigator最近实例的好状态。
pop 导航到新页面,或者返回到上个页面。
canPop 判断是否可以导航到新页面
maybePop 可能会导航到新页面
popAndPushNamed 指定一个路由路径,并导航到新页面。
popUntil 反复执行pop 直到该函数的参数predicate返回true为止。
pushAndRemoveUntil 将给定路由推送到Navigator,删除先前的路由,直到该函数的参数predicate返回true为止。
pushNamed 将命名路由推送到Navigator。
pushNamedAndRemoveUntil 将命名路由推送到Navigator,删除先前的路由,直到该函数的参数predicate返回true为止。
pushReplacement 路由替换。
pushReplacementNamed 这个也是替换路由操作。推送一个命名路由到Navigator,新路由完成动画之后处理上一个路由。
removeRoute 从Navigator中删除路由,同时执行Route.dispose操作。
removeRouteBelow 从Navigator中删除路由,同时执行Route.dispose操作,要替换的路由是传入参数anchorRouter里面的路由。
replace 将Navigator中的路由替换成一个新路由。
replaceRouteBelow 将Navigator中的路由替换成一个新路由,要替换的路由是是传入参数anchorRouter里面的路由。

二、路由导航

Flutter 通过 Navigator 来进行页面之间的跳转,分为 push 系列和 pop 系列操作,带 push 方法为入栈操作,带pop 方法为出栈操作。Navigator 的 push 方法分两类,一类是带 Name 的,需要在 MaterialApp 下将 routers 属性进行注册,否则将会找不到该路由,还有一个是不带 Name 的,可以通过 Router 直接跳转。

Navigator.of(context).push(MaterailPageRoute(builder:(context){return BPage();}))
Navigator.of(context).pop();
Navigator.of(context).maybePop();

pushNamed

pushNamed 是命名路由的方式,需要在 MaterialApp 中配置路由名称:

MaterialApp(
      title: 'Flutter Demo',
      routes: <String, WidgetBuilder>{
        '/A': (context) => APage(),
        '/B': (context) => BPage(),
      },
      home: Scaffold(
        body: APage(),
      ),
    )
  Navigator.of(context).pushNamed('/B');

pushReplacementNamed 和 popAndPushNamed
有A、B、C 三个页面,A页面通过 pushNamed 跳转到 B:
在A页面执行跳转到B

Navigator.of(context).pushNamed('/B');

在B页面执行替换并跳转跳转到C

Navigator.of(context).pushReplacementNamed('/C')

在C页面执行

Navigator.of(context).pop();

发现页面直接返回到A页面
从B页面执行Navigator.of(context).popAndPushNamed

发现popAndPushNamed 路由堆栈和 pushReplacementNamed 是一样,唯一的区别就是 popAndPushNamed 有 B 页面退出动画

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 页面'),
  onPressed: () {
    Navigator.of(context).pop();
  },
)

如果想只保留最后的D路由

 Navigator.of(context).pushNamedAndRemoveUntil('/D', (Route route)=>false);

popUntil

有如下场景,在入职新公司的时候,需要填写各种信息,这些信息分为不同部分,比如基本信息、工作信息、家庭信息等,这些不同模块在不同页面,填写信息时可以返回上一页,也可以取消,取消返回到首页,此场景可以使用 popUntil,一直 pop 到指定的页面。

RaisedButton(
  child: Text('D 页面'),
  onPressed: () {
    Navigator.of(context).popUntil(ModalRoute.withName('/A'));
  },
)

传递数据
有两种方式传递数据:
第一种:通过构造函数方式:

Navigator.of(context).push(MaterialPageRoute(builder: (context){
  return ProductDetail(productInfo: productInfo,);
})); 

通过命名路由设置参数的方式

RaisedButton(
  child: Text('A 页面'),
  onPressed: () {
    Navigator.of(context).pushNamed('/B',arguments: '来自A');
  },
)

B 页面通过 ModalRoute.of(context).settings.arguments 接收数据:

RaisedButton(
  child: Text('${ModalRoute.of(context).settings.arguments}'),
  onPressed: () {
    Navigator.of(context).pushNamed('/C');
  },
)

返回数据
B 页面返回代码

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> {
  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;
            });
          },
        ),
      ),
    );
  }
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可可鸭~

想吃糖~我会甜

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值