Flutter实战之路由功能篇

跳转功能

举例经常使用页面跳转功能。git

普通跳转

Navigator.of(context).push(
    MaterialPageRoute(
      builder: (_) => NextPage1(),
    ),
  );
复制代码

命名跳转

Navigator.of(context).pushNamed("/router/nextPage");
复制代码

前提是须要在程序主入口配置路由表github

MaterialApp(
      navigatorObservers: [UserNavigatorObserver()],
      initialRoute: "/",
      routes: {
        "/router": (context) => RouterDemo(),
        "/router/nextPage": (context) => NextPage2(),
      },
    );
复制代码

退出页面

Navigator.of(context).pop(); //直接作退出操做
Navigator.of(context).maybePop(); //若为栈中最后一个页面不作退出操做
复制代码

高级用法

popAndPushNamed

退出当前页面并跳转新页面bash

Navigator.of(context).popAndPushNamed("/router/nextPage");
复制代码

等同于以下操做数据结构

Navigator.of(context).pop();
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (_) => NextPage1(),
  ),
);
复制代码

PS: 但须要注意若是当前页为栈底根页面先执行pop再执行push会不会和popAndPushNamed执行结果不一样呢?看源码就能会发现popAndPushNamed其实就是先执行pop再执行push的操做二者执行结果同样。app

@optionalTypeArgs
  Future<T> popAndPushNamed<T extends Object, TO extends Object>(
    String routeName, {
    TO result,
    Object arguments,
  }) {
    pop<TO>(result);
    return pushNamed<T>(routeName, arguments: arguments);
  }
复制代码

pushReplacementNamed

用法和popAndPushNamed相似,一样是退出当前页面并跳转新页面。但popAndPushNamed页面出栈和入栈都有动画,pushReplacementNamed则只有入栈动画async

Navigator.of(context).pushReplacementNamed("/router/next5");
复制代码

pushNamedAndRemoveUntil

将路由栈出栈到对应命名路由而后跳转到新页面,以下所示代码“ModalRoute.withName("/")”是将路由栈退到根路由并跳转到“/router/nextPage”命名路由。 举例当前路由栈为[1,2,3,4],执行pushNamedAndRemoveUntil打开新页面5,设置 ModalRoute.withName为2,最后路由栈为[1,2,5]。经常使用场景例如在我的设置页面中多级子菜单跳转最后直接回到主页操做。ide

Navigator.of(context).pushNamedAndRemoveUntil(
                "/router/nextPage",
                ModalRoute.withName("/"),
              );
复制代码

PS: 这里要注意的是若是入栈非命名路由,不采用pushNamed入栈则ModalRoute.withName("/")会找不到要回退的位置,则跳转的页面不带返回键,也就是说栈中就只剩下一个页面。这点真的好奇是否是Flutter路由设计的问题,我暂时也没有找到ModalRoute.withName对应的方法。动画

传参功能

路由同时支持页面之间的参数传递ui

入参传递

路由跳转经过arguments字段传递想要的入参数据,咱们能够设定arguments为map对象传递更多入参。命名路由和直接路由传递arguments略有不一样,命名路由直接经过arguments字段传递,直接路由是经过settings字段建立RouteSettings对象中的arguments传递。this

  • 以命名路由跳转时
Navigator.of(context).pushNamed(
  "/router/data2",
  arguments: {"data": "Hello"},
);
复制代码
  • 以页面跳转时
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => ChildDataDemo4(),
    settings: RouteSettings(
      arguments: {"data": "Hello"},
    ),
  ),
);
复制代码

接收页面经过ModalRoute.of(context).settings获取入参arguments获得数据。

class RouterChildDateDemo2 extends StatefulWidget {
  @override
  _RouterChildDateDemo2State createState() => _RouterChildDateDemo2State();
}

class _RouterChildDateDemo2State extends State<RouterChildDateDemo2> {
  @override
  Widget build(BuildContext context) {
    Map arguments = ModalRoute.of(context).settings.arguments;
    String data = arguments['data'];
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: <Widget>[
          Text("data: $data"),
        ],
      ),
    );
  }
}
复制代码
  • 以直接路由构造方法
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => ChildDateDemo3("Hello"),
  ),
);
复制代码

数据接收页面经过widget获取入参。固然这种方式耦合性过高,对后期维护不利不推荐使用(虽然我本身项目中都是这么写,以后重构工做量巨大😿)。

class ChildDateDemo3 extends StatefulWidget {
  final String data;

  ChildDateDemo3(this.data);

  @override
  _ChildDateDemo3State createState() => _ChildDateDemo3State();
}

class _ChildDateDemo3State extends State<ChildDateDemo3> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: <Widget>[
          Text("data: ${widget.data}"),
        ],
      ),
    );
  }
}
复制代码

参数回传

除了入参外,咱们固然但愿可以在传递参数同时能够获取到返回值。好比进入一个设置页面在返回时获取到上个页面设置数据并显示(虽然全局状态管理就能很好代替这方式)。

路由跳转方法是有返回值Future,将跳转方法设置为async经过await获取结果。

var result = await Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => ChildDataDemo5(),
  ),
);
setState(() {
  this.result = result.toString();
});
复制代码

当要返回上级页面回传结果时在pop方法中传递须要返回泛型参数(使用字典是比较好的数据结构)。

Navigator.of(context).pop({"data": "Bye"});
复制代码

动画过渡

替换MaterialPageRoute使用PageRouteBuilder作路由跳转。经过transitionsBuilder建立AnimatedWidget对象实现动画效果。以下设置一个SlideTransition滑动过渡动画经过起始和结束的偏移量达到侧边滑出效果

Navigator.of(context).push(
  PageRouteBuilder(
    pageBuilder: (BuildContext context,
        Animation<double> animation1,
        Animation<double> animation2) {
      return AniDemo2();
    },
    transitionsBuilder: (BuildContext context,
        Animation<double> animation1,
        Animation<double> animation2,
        Widget child) {
      return SlideTransition(
        position: Tween<Offset>(
          begin: Offset(-1.0, 0.0),
          end: Offset(0.0, 0.0),
        ).animate(
          animation1,
        ),
        child: child,
      );
    },
  ),
);
复制代码

Demo代码地址

可参考demo了解路由代码和路由使用。

参考

相关文章
相关标签/搜索