Flutter入門進階之旅(十三)Flutter 路由

Flutter路由介紹

跟Web頁或者原生APP一樣,我們在使用Flutter 開發APP時也會涉及到多頁面之間的跳轉、參數傳遞、參數回傳等業務,Flutter路由能滿足上述我們提到的所有業務類型,此外我們也可以結合Flutter動畫給路由跳頁時添加個性化的跳頁動畫操作,我會在后續Flutter動畫章節中具體講解。通過本節專題,讀者不僅僅可以自己動手做一些簡單的UI,還能利用Fluttter 路由結合之前的課程分享做一些簡單的多頁面Flutter App。

本期課程目標
  • 了解并掌握Flutter路由的簡單使用
  • 掌握Flutter動態路由跟靜態路由的區別
  • 掌握Flutter路由在頁面間的參數傳遞以及回傳流程
  • 借助路由結合之前的課程做一些簡單的多頁面Flutter APP

關于靜態路由跟動態路由

在Flutter中路由分為靜態路由動態路由兩種:Flutter中所謂的靜態路由指的是需要提前把各個需要跳轉的頁面路徑注冊在routes: <String, WidgetBuilder> {}中,且靜態路由不支持向下一個頁面傳遞參數,但是可以接收下一個頁面的返回值
動態路由使用就相對來說比較靈活一點,動態路由同樣支持向下一個頁面傳遞參數,而且在使用時不需要我們提前規劃好頁面路徑,只需要在具體跳頁邏輯中自己去構造MaterialPageRoute對象來完成頁面跳轉,或者用PageRouterBuilder來自定義路由跳轉時的動畫,關于路由跳轉動畫我會在Flutter動畫章節中具體講解,當然動態路由同樣也支持頁面參數回傳。

路由場景分類

1.靜態路由跳頁

場景一:點擊A頁面中的按鈕跳轉到B頁,不涉及到數據傳遞以及回傳

效果圖

靜態路由跳頁

靜態路由使用時要求我們在MaterialApp中的routes中提前注冊路由

new MaterialApp(
      home: new FlutterDemo(),
      routes: <String, WidgetBuilder>{
        'router/new_page': (_) => new StaticNavigatorPage()
      }));
      

A頁面代碼

import 'package:flutter/material.dart';
import 'package:flutter_app/pages/simpleWidget/navigator/StaticNavigatorPage.dart';

void main() {
  runApp(new MaterialApp(
      home: new FlutterDemo(),
      routes: <String, WidgetBuilder>{
        'router/new_page': (_) => new StaticNavigatorPage()
      }));
}

class FlutterDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Flutter進階之旅"),
      ),
      body: new Center(
          child: new RaisedButton(
              child: new Text("靜態路由跳頁"),
              onPressed: () {
                Navigator.of(context)
                    .pushNamed('router/new_page'); //這里一定要保證跳頁的路由路徑跟上面注冊的路徑一致
              })),
    );
  }
}

B頁面代碼

import 'package:flutter/material.dart';

class StaticNavigatorPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("靜態路由頁"),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          Navigator.of(context).pop();
        },
        child: new Text("返回"),
      ),
      body: new Center(
        child: Text("靜態路由可以傳入一個routes參數來定義路由。但是這里定義的路由是靜態的,"
            "它不可以向下一個頁面傳遞參數,利用push到一個新頁面,pushNamed方法是有一個Future的返回值的"
            ",所以靜態路由也是可以接收下一個頁面的返回值的。但是不能向下一個頁面傳遞參數"),
      ),
    );
  }
}

上述借助路由跳頁過程中我們注意到,大概分以下幾步:
1.注冊路由且保證路由的唯一性
2.跳頁時使用Navigator.of(context).pushNamed('路由地址');
3.使用Navigator.of(context).pop();結束當前頁

2.靜態路由跳頁接收下一頁的返回值

場景二:點擊A頁面上的按鈕跳頁到B頁面,在B頁面銷毀后A頁面接收到B頁面回傳回來的值并且顯示在AlertDialog

效果圖

靜態路由回傳數據

A頁面代碼:
使用Navigator push一個新頁面,pushNamed方法是有一個Future的返回值的,在then回調中監聽并接收新頁面回傳回來的數據,并且借助showDialog顯示在Dialog

import 'package:flutter/material.dart';
import 'package:flutter_app/pages/simpleWidget/navigator/StaticNavigatorPageWithParams.dart';

void main() {
  runApp(
      new MaterialApp(home: new FlutterDemo(), routes: <String, WidgetBuilder>{
    'router/new_page_with_callback': (_) => new StaticNavigatorPageWithResult()
  }));
}

class FlutterDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Flutter進階之旅"),
      ),
      body: new Center(
          child: new RaisedButton(
              child: new Text("靜態路由接收下一頁返回值"),
              onPressed: () {
                Navigator.of(context)
                    .pushNamed('router/new_page_with_callback')
                    .then((value) {
                  showDialog(
                      context: context,
                      child: new AlertDialog(
                        content: new Text(value),  
                      ));
                });
              })),
    );
  }
}

B頁面代碼:

從效果圖中可以看到,當我點擊B頁面中間的按鈕時會把數據回傳給上一頁,但是直接點擊導航欄左上角的返回按鈕回到A頁面時并不會把數據傳遞給上一個頁面,這里是因為我在B頁面的按鈕上pop頁面出棧的時候把參數放進里面作為了參數傳遞,pop()可接收一個Object對象作為參數傳遞

Navigator.of(context).pop(T extends Object);

這就告訴我們當我們需要給上一個頁面回傳數據的時候可直接借助pop傳遞Navigator.of(context).pop("頁面結束后返回的數據");,不需要傳值的時候直接返回空對象Navigator.of(context).pop()即可。

import 'package:flutter/material.dart';

class StaticNavigatorPageWithResult extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("靜態路由帶返回參數"),
      ),
      body: new Center(
        child: new OutlineButton(
          onPressed: () {
            Navigator.of(context).pop("頁面結束后返回的數據");
          },
          child: Text("點我返回上個頁面結束后返回的數據"),
        ),
      ),
    );
  }
}

3.動態路由跳頁

文章的開頭我們提到借助動態路由可以向下一個頁面傳遞參數,同樣也可以接收新頁面回傳回來的數據。下面我模擬兩個使用動態路由的場景,既然動態路由可以傳值那就肯定可以不傳值跳頁,我就不模擬動態路由不傳值跳頁的例子了,讀者借助靜態路由的樣例自行測試即可,我們主要講解一下借助動態路由傳值的例子。

場景三:點擊A頁面中的按鈕,把用戶名跟密碼傳遞給下一個頁面B頁面,B頁面處理完接收到的數據后把結果回傳給A頁面,A頁面中把從B頁面回傳回來的數據顯示在Dialog上。

模擬效果圖

動態路由傳遞參數

使用動態路由時我們不再需要像靜態路由那樣在MaterialApp中的router中提前注冊路由路徑,只需要在使用Navigator.push傳入MaterialPageRoute對象即可

 Navigator.push(
    context,
    new MaterialPageRoute(
        //_代表參數為空
        builder: (_) => new DynamicNaviattionPage(
              username: "xiedong",
              password: "123456",
            )));

A頁面代碼:

import 'package:flutter/material.dart';
import 'package:flutter_app/pages/simpleWidget/navigator/DynamicNavigationPage.dart';

void main() {
  runApp(new MaterialApp(home: new FlutterDemo()));
}

class FlutterDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("Flutter進階之旅"),
        ),
        body: new Center(
            child: new RaisedButton(
          onPressed: () {
            Navigator.push(
                context,
                new MaterialPageRoute(
                    //_代表參數為空
                    builder: (_) => new DynamicNaviattionPage(
                          username: "xiedong",
                          password: "123456",
                        ))).then((value) {
              showDialog(
                  context: context,
                  child: new AlertDialog(
                    content: new Text(value),
                  ));
            });
          },
          child: new Text("動態路由傳參"),
        )));
  }
}

B頁面代碼:

import 'package:flutter/material.dart';

class DynamicNaviattionPage extends StatelessWidget {
  var username;
  var password;

  DynamicNaviattionPage({Key key, this.username, this.password})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("動態路由"),
      ),
      body: new Center(
        child: new Column(
          children: <Widget>[
            new MaterialButton(
              onPressed: () {
                Navigator.pop(context, "未查詢到改該用戶信息");
              },
              child: new Text("點我返回"),
              color: Colors.lightGreen,
            ),
            new Text("上頁傳遞過來的username   $username"),
            new Text("上頁傳遞過來的password   $password"),
          ],
        ),
      ),
    );
  }
}

關于路由重點總結

  • Flutter路由分為靜態路由跟動態路由,靜態路由不支持向下一個頁面傳遞參數,動態路由可傳遞
  • 靜態路由使用時需要提前注冊聲明頁面路徑,
  • 動態路由可以直接在使用時構造路由對象,不需要提前注冊路徑。
  • 兩種類型都支持接收下一頁面回傳回來的值

下一篇:Flutter入門進階之旅(十四)ListView&GridView

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容