CodeZine(コードジン)

特集ページ一覧

Flutter2の新しい画面遷移「Navigator 2.0」を使ったページ遷移を理解しよう

Flutterで始めるモバイルアプリ開発 第10回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2021/08/05 11:00

 今回は、前回に引き続き画面遷移について説明します。Flutter2では、新しい画面遷移の仕組み(Navigator 2.0)が導入されました。この新しい画面遷移の方法は、少々複雑でわかりにくいところがあります。また、アプリ開発だけの場合であれば、必ずしもこの仕組みを導入する必要もないと思っています。しかし、Flutter2で正式サポートされたWebアプリなどを今後想定する場合や、新しい流れの参考としてご紹介します。まだまだ利用ノウハウなども多くないため、今後の参考として捉えていただければと思います。

目次

Navigator 2.0と以前のバージョンとの大きな違い

 これまでの画面遷移(以下、Navigator 1と示す)は、画面上のアクションに応じて、画面変更を命令するという流れでした。それに対して、Navigator 2.0(以下、Navigator2)では、画面スタックの状態を管理するというようになっています。文章で説明しても、少々イメージがわきにくいというところもあるので図1のように違いを示しました。

図1:Navigator1とNavigator2の大きな違い
図1:Navigator1とNavigator2の大きな違い

 例えばNavigator1では、PUSH/POPという概念を使って、画面スタックを変更します。PUSHであればスタック上の一番上に追加し、POPであれば一番上から画面を取り除くというようにです。これらの説明は前回したので、詳しくはそちらを参照してください。

 Navigator2では、画面スタックを直接コントールすることで画面の切り替えを行い、それに合わせてパスなどを変更します。そのため、明示的な画面変更方法ではなく概念的で少々わかりにくくなるかと思います。

 また、パスを使った操作については、必ずしも必要なわけではありません。もちろん、パスを利用しない場合にはそのメリットがなくなります。しかし、構造としてわかりやすくなるため、まずはパスを使った画面遷移を使わない場合を説明し、その後パスを使った画面遷移を使う場合として説明します。

パスを使わない場合のNavigator2の利用方法

 まずは、シンプルな構造で、Navigator2での画面スタックのコントロールに主に焦点をあてた説明します。このサンプルの動作イメージとプログラムの主要な要素との関係をあらわしたのが図2です。

図2:パスを使わない場合の動作イメージと主要要素の関係
図2:パスを使わない場合の動作イメージと主要要素の関係

 各画面であるProductListPageとProductItemPageは、双方共にWidgetのサブクラスです。このプログラムについての説明は今回は割愛させていただきます。また、データを管理するクラスとしてProductItemクラスを用意しました。このクラスのコードがリスト1です。

[リスト1]Navigatorのpushを使ったコード例(lib/ProductItem.dart)
class ProductItem {
    final String id;      // (1) データのID(パスを使ったサンプルで利用)
    final String title;   // (2) データのタイトル(一覧のタイトル・詳細画面のタイトル)
    ProductItem(this.id, this.title);
}

 そして、Navigator2を使った画面遷移のプログラムがリスト2です。

[リスト2] Navigator2を使った画面遷移例(lib/main_1.dartの抜粋)
class _MainApp1 extends State<MainApp1> {
  //  (1) 詳細画面として表示する場合のデータ
  ProductItem _selectedItem;

  //  (2) ProductListPageでListをタップした時に呼ばれるメソッド
  void _onTapItem(ProductItem item) {
    setState(() {
      _selectedItem = item;
    });
  }
  //  (3) 管理しているデータ
  List<ProductItem> items = [
    ProductItem("id1", "商品A"),
    ProductItem("id2", "商品B")
  ];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Nav2 Sample 1',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        //	(4) 最初のページとしてNavigatorクラスを指定する
        home: Navigator(
          // (5) 表示する画面スタック
          pages: [
            MaterialPage(child: ProductListPage(this.items, _onTapItem)),
            //	(6) 詳細画面を表示する時には、画面を追加する
            if (_selectedItem != null)
              MaterialPage(child: ProductItemPage(_selectedItem)),
          ],
          //  (7) popが呼ばれた時の処理 ( pages[]を指定したら、必ず必要です )
          onPopPage: (route, result) {
            // (8) popできる画面がない場合の対応
            if (!route.didPop(result)) {
              return false;
            }
            // (9) popできた場合には、データをクリアする
            setState(() {
              _selectedItem = null;
            });
            return true;
          },
        ));
  }
}

 (1)は、詳細画面を表示する際のオブジェクトを管理するための変数です。このオブジェクトがnullの場合には一覧画面の表示とし、インスタンスが設定されている場合には、詳細画面が表示されるということを想定しています。

 (2)の_onTapItemメソッドは、一覧画面の各リストアイテム部分がタップされた時にコールされることを想定したメソッドです。タップされると詳細画面を表示するためのインスタンスを(1)の変数に設定します。また、この変数が設定されたタイミングで画面更新が生じるようにsetStateを使ってオブジェクトを設定しています。

 (3)は、今回表示するデータの一覧です。実際の利用ケースでは、このデータをネットワークから取得するような場合が多いはずです。

 そして、Navigator2では、(4)のようにMaterialAppのhomeプロパティにNavigatorクラスを指定します。今までの例では、Navigatorクラスはスタティックな利用でしたが、今回はWidgetとして扱っています。

 (5)のpagesプロパティが、実際のページスタックを管理している部分です。_selectedItemにインスタンスが設定されている場合には、詳細画面を表示する必要があるので、(6)のように画面スタックに追加します。この配列の順番が画面スタックになるので、順番を反対にすると表示されません。

 また、(7)が、戻るボタンなどを押した場合、つまりpopが呼び出された場合にどのような動作をするかを定義します。一覧が画面が表示されている場合には戻るべき画面はないため、(8)のように処理を抑制しています。

 そして、今回の例では戻るボタンは詳細から一覧画面への戻る操作になるため、(9)のように既に選択されたいたデータをクリアし、画面を更新します。以上のように一見複雑に見えますが、やっていることはNavigatorクラスのpagesプロパティを変更することです。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:Flutterで始めるモバイルアプリ開発

もっと読む

著者プロフィール

  • WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。個人紹介主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしど...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5