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瞭解路由代碼和路由使用。

參考

相關文章
相關標籤/搜索