実践Flutter

Flutterでスマホを中心にアプリ制作していきます。

Flutterのページ遷移2・GetXでパラメタ渡しとアニメーション

はじめに

前回に引き続き今回もFlutterのページ遷移についてポイントをまとめて行きます。今回は特に遷移時のパラメタ渡しページ遷移アニメーションの設定にフォーカスを当てていきます。

前回と同じ画面の例題を使いますので、サンプルコードがごついのですが、今回フォーカスする部分はほんの少しです。全体のコードの流れは前回の記事をご参照ください。

今回もGetXライブラリを活用していきます。こちらも導入を前回の記事で行っていますのでGetXに馴染みのない方はそちらをご参照ください。





パラメタ受け渡し・ページ遷移アニメ設定

前回の画面・遷移の構成は変えず、画面遷移時のパラメタ受け渡しと、遷移時のアニメーション設定を追加したサンプルを示します:

import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {

    return const GetMaterialApp(
      debugShowCheckedModeBanner: false,
      initialRoute: '/',
      //(1) デフォルトのページ遷移アニメーションを設定
      transitionDuration: Duration(milliseconds: 400),
      defaultTransition: Transition.upToDown,
      home:Home(),
    );
  }
}

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Home Screen"),
      ),
      body:Column(
          children:[
            const Padding(
                padding: EdgeInsets.only(top:50)
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children:[
                ElevatedButton(
                  //(2) 個別のページ遷移アニメーションの設定も可能
                  onPressed: ()=>Get.to(()=>const First(), transition: Transition.rightToLeft),
                  child: const Text("to First"),
                ),
                ElevatedButton(
                  //(3) Second()への遷移の際、パラメタを受け渡す例
                  onPressed: ()=>Get.to(()=>const Second(), arguments: {"arg1":1, "arg2":"a"}),
                  child: const Text("to Second"),
                ),
              ],
            )
          ]
      ),
    );
  }
}

class First extends StatelessWidget {
  const First({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("First Screen"),
      ),
      body:Column(
          children:[
            const Padding(
                padding: EdgeInsets.only(top:50)
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children:[
                ElevatedButton(
                  onPressed: ()=>Get.back(),
                  child: const Text("Back"),
                ),
              ],
            )
          ]
      ),
    );
  }
}

class Second extends StatelessWidget {
  const Second({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    //(4) パラメタの受け取り
    var args = Get.arguments;

    return Scaffold(
      appBar: AppBar(
        title: const Text("Second Screen"),
      ),
      body:Column(
          children:[
            const Padding(
                padding: EdgeInsets.only(top:50)
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children:[
                ElevatedButton(
                  onPressed: ()=>Get.to(()=>const Third()),
                  child: const Text("to Third"),
                ),
                ElevatedButton(
                  onPressed: ()=>Get.off(()=>const Third()),
                  child: const Text("off Third"),
                ),
                ElevatedButton(
                  onPressed: ()=>Get.offAll(()=>const Third()),
                  child: const Text("off all Third"),
                ),
              ],
            ),
            const Padding(
              padding:EdgeInsets.only(top:50)
            ),
            const Text("Parameters:"),
            //(5) 受け渡されたパラメタの内容を確認
            Text("Param1:"+(args["arg1"]?.toString()?? "no param")),
            Text("Param2:"+(args["arg2"]?.toString()?? "no param")),
          ]
      ),
    );
  }
}


class Third extends StatelessWidget {
  const Third({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Third Screen"),
      ),
      body:Column(
          children:[
            const Padding(
                padding: EdgeInsets.only(top:50)
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children:[
                ElevatedButton(
                  onPressed: ()=>Get.offAll(()=>const Home()),
                  child: const Text("Go Home"),
                ),
              ],
            )
          ]
      ),
    );
  }
}

全体の画面遷移の様子の説明は前回の記事にゆずります。遷移時のアニメーションについては、実行して見てみて下さい。

「Home」画面から「Second」画面に移るときにパラメタの受け渡しを行っています。これを確かめるために、「Second」画面描画時に、受け取ったパラメタを表示するようになっています:

f:id:linkedsort:20211018000937p:plain:w400

下部の「Parameters」のところに、受け取ったパラメタを表示しています。

コードのポイント

(1) ページ遷移アニメーションの基本設定
    return const GetMaterialApp(
      debugShowCheckedModeBanner: false,
      initialRoute: '/',
      //(1) デフォルトのページ遷移アニメーションを設定
      transitionDuration: Duration(milliseconds: 400),
      defaultTransition: Transition.upToDown,
      home:Home(),
    );

GetXのページ遷移アニメーション全体を設定するには、起点となるGetMaterialAppの属性を設定します。

transitionDurationはページ遷移するときの時間の長さで、上記では400ミリ秒(0.4秒)の設定にしています。

defaultTransitionは様々なTransitionクラスの値を取ります。下記に一部をあげますが、色々試して動きを見てみて下さい:

Transitionの値 動き
Transition.upToDown 上から下に向かって出現
Transition.downToUp 下から上に向かって出現
Transition.rightToLeft 右から左に向かって出現
Transition.leftToRight 左から右に向かって出現
Transition.fade フェードインしながら下から上に向かって出現
Transition.leftToRightWithFade フェードインしながら左から右に向かって出現
Transition.cupertino 右から左方向に元ページがフェードアウト、下から上に新ページがフェードイン
Transition.cupertinoDialog 右から左に向かって出現・ページのエッジに影
Transition.native 下から上に向かってフェードイン
Transition.noTransition 瞬間切り替え・アニメーションなし

遷移の動きを選ぶときは、戻るボタンでページを戻す操作も対になっていますので、そちらも確認して動きのイメージの合うものを選んで下さい。

(2) 個別のページ遷移アニメーション設定
   ElevatedButton(
     //(2) 個別のページ遷移アニメーションの設定も可能
     onPressed: ()=>Get.to(()=>const First(), transition: Transition.rightToLeft),
     child: const Text("to First"),
   ),

(1)ではアプリ全体のデフォルトのページ遷移アニメーション設定を行いましたが、その上で個別の遷移のアニメーションを上書きで設定できます。

Get.toなどの遷移の引数のなかで、transitonパラメタを与えるとこの遷移だけのアニメーションを設定できます。

またサンプルでは与えていませんが、durationパラメタでアニメーションの時間も個別に設定できます。

(3) ページ遷移時のパラメタの受け渡し
   ElevatedButton(
     //(3) Second()への遷移の際、パラメタを受け渡す例
     onPressed: ()=>Get.to(()=>const Second(), arguments: {"arg1":1, "arg2":"a"}),
     child: const Text("to Second"),
   ),

ページ遷移時にパラメタを受け渡す場合は、Get.toなど遷移メソッドのargumentsパラメタを設定します。argumentsの型はdynamicなので、何を渡してもOKです。1つの数値でも、リストでも、集合でもなんのオブジェクトでもそのまま渡ります。

ただコードの可読性、再利用性、複数の値を受け渡すときの利便性などを考慮すると写像で渡すのが最もよく採用されるパターンかと思います。上記例では「文字列→整数および文字列の写像」を渡しています。受け取り側と呼吸があっていればなんでもOKです。

遷移時パラメタの受け取り
    //(4) パラメタの受け取り
    var args = Get.arguments;

遷移時にargumentsに設定されたオブジェクトを受け取ります。もともとdynamic型なので任意の型になりえます。

コンパイラはチェックしません、ということですのでしっかり型を整合させるようにして下さい。

(5) パラメタの内容確認
   //(5) 受け渡されたパラメタの内容を確認
   Text("Param1:"+(args["arg1"]?.toString()?? "no param")),
   Text("Param2:"+(args["arg2"]?.toString()?? "no param")),

ここではargsが写像として渡されることが分かっていますので、写像として扱っています。

サンプルでは固定的な値を渡しているのでargs["arg1"]及びargs["arg2"]がnullにならないことは分かっていますが、念の為nullだった場合の対処を書いています。xがnullだった場合「x?.toString()」はnullになりますので、「??」でつないでnullだった場合は"no param"を出力させるようにしています。

「?.演算子」「??演算子」に馴染みがない場合はnullable/non-nullableの回演算子の回の説明を御覧ください。





おわりに

今回はページ遷移のときのパラメタ受け渡しと、遷移時のアニメ演出についてポイントを解説しました。

GetXはその設計思想のシンプル記述の通り、ほとんど無駄な記述がなくて嬉しいですよね。なので書き方を抑えておけばほとんどハマりどころはないのではないかと思います。

とはいえ初学のときは変なところでハマるものなので、一旦動くコードから初めて色々いじってみて下さい




[:plai