穿梭在不同的畫面中 - 直接導航法

紅寶鐵軌客
Join to follow...
Follow/Unfollow Writer: 紅寶鐵軌客
By following, you’ll receive notifications when this author publishes new articles.
Don't wait! Sign up to follow this writer.
WriterShelf is a privacy-oriented writing platform. Unleash the power of your voice. It's free!
Sign up. Join WriterShelf now! Already a member. Login to WriterShelf.
寫程式中、折磨中、享受中 ......
617   0  
·
2021/06/02
·
7 mins read


通常一個 App 都會有很多個畫面,在 Flutter 中,大家好像都是用「Screen」來稱呼「畫面」,所以我們以後也統一就叫「Screen」了。

繼續我們的「happy recorder 快樂錄音機」開發,在使用者的情境中,這個 App 需要至少會兩個 Screens:

  • 程式開始:畫面停在「錄音列表」Screen,
  • 錄音列表」Screen:
    • 使用者點 <+> 按鈕,跳到「新增及修改錄音」Screen 的『新增』動作,
  • 新增及修改錄音」Screen 的『新增』動作:
    • 點<停止錄音>按鈕:畫面跳回「錄音列表」Screen。


    Flutter 2 有四種切換 Screen 的方式

    什麼!有四種!是的,在 Flutter 中,切換跳到不同的 Screen 被稱為 Navigation(導航)& Routing(路由),Flutter 到目前為止,提供了四種 Navigation & Routing 的方式:

    N1
    直接導航
    直接給指定 screen 名稱
    N2 固定名稱路由 透過路由跳到指定的 screen 名稱
    N3 動態名稱路由 目的地由 widget 中取出,或用 onGenerateRoute()  
    N4 動態名稱路由 2.0 使用 State:有 Page 及 Route 兩個新的 API
    為什麼有四種?

    不能一種就好嗎?嗯,有一個很大的挑戰,就是為了要支援網頁。 別忘了 Flutter 不只是能產生 App,還能產生 Web,只是 Web 跟 App 有個很大的不同,例如:

    • Web 是在瀏覽器上執行,它有一個「使用者可以亂寫的網址列」,
    • App 執行一定是從首頁開始,Web 可就不一定了,舉例來說,下面是一個很典型的網址(這是我的另一本書): 
    https://www.writershelf.com/book/rails-實作

    任何人都可以在瀏覽器上輸入這個網址,然後就直接可以看到這本書了,並不需要從網站的首頁開始。也就是為了要支援架設網站,所以 Flutter 才有了其他三種 N2/N3/N4 方法。

    我要用那一種呢?

    如上所述,會有那麼多種方法,都是為了支援網頁,所以,要選擇用那個一種方式,基本上也是取決於網頁的需求,大致如下:

    N1
    直接導航
    App 不需要支援網頁、Screen 也不多
    N2 固定名稱路由 App 支援網頁、但 Screen 名稱固定
    N3 動態名稱路由 App 支援網頁、Screen 名稱是變動的
    N4 動態名稱路由 2.0 App 支援網頁、Screen 是由 State 切換

    接下來,我們就來看看怎麼用這些方法吧。


    N1 / 直接導航:

    這個最簡單,超級簡單,基本上你要去哪一個 screen,就直接給它的 widget 名稱就好。

    註:如果你是插隊進來,沒有看過前一篇文章,之前的程式碼在這裡:

    開始寫第一個 Flutter 2 程式 — 如果你照著我之前寫的安裝程式,你的 Android Studio 跟 Flutter 2 SDK 應該都已經裝好了,所以我們現在就可以開始寫 Flutter 了。 寫程式前有一個很重要的建議,...
    WriterShelf 思書: 紅寶鐵軌客

    來請跟著我做:新增一個 「新增及修改錄音」Screen,這自然是一個 Widget,就叫 AudioSession 吧,你可以 copy & paste 在原來程式的最後面。

    class AudioSession extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Record"),
            automaticallyImplyLeading: false, // not display <- back btn
          ),
          body: Center(
            child: ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: Text('Go back!'),
            ),
          ),
        );
      }
    }

    這就是一個很簡單的 StatelessWidget screen,用 Scaffold 直接建立一個 title 及一個上面是「Go back!」的按鈕,這裡面只有幾行你沒看過,讓我們來說明一下:

    • 第 7 行:automaticallyImplyLeading: false 是將倒退鍵取消,等一下你可以把它 remark 起來,你就知道這時什麼了。
    • 第 10 行:這是 flutter 中所提供的 Material design 按鈕:
      • Flutter 中的各式 buttons,可以看這裡
      • 有關 Material design 的按鈕,可以看這裡
    • 第 12 行:Navigator.pop,這是我們的重點,navigator 也是一個 Widget,這是 navigator 管理 screen 切換的一個方法,navigator 就是個堆疊,可以把它想像成是一個坑,你要去那裡就是把目的 screen「push 推」入坑,要回去的話,就把它從坑裡「pop 拉」出。還是不懂?別急,等一下我們來畫個圖詳細介紹你就懂了。

    再來,我們修改一下 _MyHomePageState 中的 floatingActionButton,程式碼如下:

    floatingActionButton: FloatingActionButton(
      //onPressed: _incrementCounter,
      onPressed: () {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => AudioSession()),
        );
      },
      tooltip: 'new recording',
      child: Icon(Icons.add),
    ),

    其實也沒改什麼,就是將:

    • 第 3~8 行:原來的 onPress 是呼叫 _incrementCounter,現在改成 Navigator.push,記得我們剛剛說過的,navigator 管理 screen 切換是用堆疊,可以想像成是一個坑,你要去那個 screen,就是它「push 推」入坑就好了,這裏,我們就把一個包著 AudioSession() 的 MaterialPageRoute 推入坑了,注意,這裡推入坑的是一個包著畫面的 MaterialPageRoute,為什麼不直接把畫面推入坑呢?因為畫面切換還有轉場動畫效果要做,我們以後會再介紹轉場動畫,MaterialPageRoute 不只做畫面切換還要做平台相關的切換動畫
    • 第 9 行:不過就是改了些說明文字。

    來來來,快,我們趕快來看看執行結果,按一下 run 鍵,哇哈,可以切換 screen 了。


     好像有點太簡單了,就一個 push 跟 pop,Screen 就可以切換了。還有,上面的這張也加上了「Navigator 堆疊」示意:

    1. 當左邊 MyHomePage 的<+>按鈕按下後,AudioSession 就被推入堆疊中,所以畫面也切換到 AudioSession。清注意,這時有 MyHomePage 還同時存在,並沒有被刪除。
    2. 當又邊 AudioSession 的<Go back!>按鈕按下後,AudioSession 就被 pop 拉出堆疊,所以畫面也切換回 MyHomePage。


    請把 AudioSession 中的 automaticallyImplyLeading 前面,加上 //,也就是把它 remark 起來,再 run 一下程式,有看到什麼差別嗎!? 啊,App Bar 上出現了一個倒退鍵,沒錯,這行就只是把 App Bar 前面的倒退鍵藏起來而已。

    如果你就只要開發 iOS 或 Android App,screen 也不多的話,這個方法其實很夠用,但是如果是要在 Web 上使用,可能就不夠力了,所以,現在請在 Web 上測試看看(在 Andrio Studio 的模擬器選 web,按 run 按鈕),哈哈哈,很高興吧,很順暢的切換網頁,但是請注意,瀏覽器上的網址在切換網頁時並沒有改變,它一直保持如下圖般的「永恆」,是的,這就是新式「有點」流行的「SPA」Single-Page Application,單頁應用網站,有不少人很喜歡這種網頁,SPA 當然有優點也有缺點,不過真正的問題是:這是你要的嗎?

    很不幸的,這不是我們要的,我們需要一個網址可以直接連到錄音檔,像是:url.com/audio/class1。

    另外,各位也可以玩玩瀏覽器的倒退前進鍵,我想信你應該很快就會發現怪怪的,有的時候可以倒退,有時不行,這就是惡名昭彰的瀏覽器歷史紀錄控制問題,例如:使用者登入後,如果按了瀏覽器倒退,登入畫面就又跳出來了,各位使在 Flutter 開發網站時,務必要多測試瀏覽器歷史紀錄控制,Flutter 的四種切換 Screen 方式都有不同效果,各有好壞,合用及動作正確就是好方法。

    沒關係,還好 Flutter 有四種切換 Screen 的方式,讓我們繼續看下一種。





    WriterShelf™ is a unique multiple pen name blogging and forum platform. Protect relationships and your privacy. Take your writing in new directions. ** Join WriterShelf**
    WriterShelf™ is an open writing platform. The views, information and opinions in this article are those of the author.


    Article info

    This article is part of:
    Categories:
    Tags:
    Date:
    Published: 2021/06/02 - Updated: 2021/06/09
    Total: 1856 words


    Share this article:
    About the Author

    很久以前就是個「寫程式的」,其實,什麼程式都不熟⋯⋯
    就,這會一點點,那會一點點⋯⋯




    Join the discussion now!
    Don't wait! Sign up to join the discussion.
    WriterShelf is a privacy-oriented writing platform. Unleash the power of your voice. It's free!
    Sign up. Join WriterShelf now! Already a member. Login to WriterShelf.