Chapter 06

動くアプリを作ってみよう

今回はついに画面を操作して動くアプリを作ります。


完成アプリ

アプリの動作内容

  • サイコロをタップすると、サイコロの目がランダルに変わる
  • 2 つのサイコロどちらをタップしても、両方の目が変わる

このチャプターで学べること

  1. アプリに機能を持たせる方法
  2. 関数の扱い
  3. stateless/stateful の違い

ソースコードは github にあげています。

https://github.com/o-matsu/zenn_flutter_beginnersbook/tree/main/chapter06_dicee

アプリの構成

前回同様、実装に必要なウィジェットの構成を整理します。


ウィジェット構成
レイアウトについては前回とほぼ同じですが、今回は横並びになので、Column ではなく、Row を使っています。

ウィジェットの説明

今回新たに登場した 2 つのウィジェット(Expand, FlatButton)について、説明します。

Expand

画面内に収まるように、子要素のサイズをいい感じに調整してくれる便利なやつです。同階層に複数の Expand を並べて、Flex プロパティに数字を指定する事で、相対的に大きさを決める事ができます。

画像やアイコンのサイズなど、絶対値で指定しまうと、デバイスの画面サイズによって表示が崩れる事があるので、相対指定できる Expand は多用しそうですね。

今回は 2 つのサイコロのサイズは同じにしたいので、flex プロパティは指定していません。flex は既定値として 1 が設定されています。

FlatButton

このアプリの核となるボタン系のウィジェットです。ユーザーがボタンをタップした時に任意の処理を呼び出す事ができます。ボタン形のウィジェットには、他にも IconButton や FloatingActionButton があります。

タップ時の処理は onPressed プロパティに void 関数(返り値なしの関数)として記述します。2つのボタンから同じ処理を行う為、処理を別の関数(changeDiceFace)で定義して onPressed から呼び出しています。

main.dart
onPressed: () {
  changeDiceFace();
},

changeDiceFace 関数では、表示されるサイコロの目をランダムに変更しています。サイコロの目は、左右それぞれ変数(leftDiceNumber, rightDiceNumber)に格納しています。これらの変数は予め初期化しておく必要があります。

main.dart
void changeDiceFace() {
  setState(() {
    leftDiceNumber = Random().nextInt(6) + 1;
    rightDiceNumber = Random().nextInt(6) + 1;
  });
}

変数を用いた画像ファイルの表示

サイコロの目によって、表示される画像を変える為に、Image ウィジェットでの画像ファイルの指定に変数を利用しています。

main.dart
child: Image.asset('images/dice$leftDiceNumber.png'),

このように$を頭につけると文字列内で変数を呼ぶ事ができます。

実装のポイント

Stateful ウィジェット

今回サイコロの目を変数に格納して、表示内容を動的に変化させています。このように状態の変化が起こる場合には、Stateful ウィジェットを使う必要があります。前回まで利用していた Stateless ウィジェットでは、基本的に動的に表示を変える事ができません。その分表示速度等のパフォーマンスに優れているので、全てを Stateful にすれば良いという事ではなく、適材適所で使い分けていく必要があるようです。

また、さらに複雑なアプリケーションになると、Stateful によるウィジェット内での状態保管では、ツリー構造上離れた場所にあるウィジェットとの連携が難しくなるという課題もあるようです。この場合、状態管理はウィジェットとは切り離された領域で管理することになります。この管理方法は流行りの手法がころころ変わっているようです。執筆時点(2020 年末)では、Riverpod というものが流行っているようです。

まとめ

ようやく動くアプリを作る事ができました。なかなか勉強の時間が取れず、牛歩のような進め方ですが、地道に続けていこうと思います。次回は、楽器アプリを作成します。お楽しみに。