Flutter:ダイアログで入力した値を呼び出し元の画面に渡す
タイトル通り、ダイアログで入力した値を呼び出し元の画面に渡す方法について紹介します。
学習用に作成したカウントダウンタイマーでは、タイマーの制限時間を設定する際に、ダイアログを表示しています。
そして、このダイアログに入力した制限時間を、呼び出し元画面のタイマーに設定する実装としています。
本記事では、この動作の実装方法について紹介します。
実装したダイアログの機能は次の通りです。
- タイマーの制限時間(秒数)を入力できる。
- ダイアログ中のOKボタンを押下すると、呼び出し元画面に入力した秒数を渡し、ダイアログを閉じる。
- ダイアログ中のキャンセルボタンを押下すると、呼び出し元画面にnullを渡し、ダイアログを閉じる。
ダイアログのWidgetを作成する
まずは、ダイアログをStatefulWidgetで作成します。
そして、Widgetをbuildする際は、AlertDialogを利用します。
AlertDialogは今回のようなレイアウトのダイアログを作成する際に便利です。AlertDialogのプロパティとレイアウトの関係は次の通りです。
そして、今回は次のようにダイアログのWidgetを実装しました。
それでは、AlertDialogのプロパティに設定したWidgetについて見ていきます。
- title
Textでtitle部に表示する文字列を設定しています。 - content
制限時間を入力するために、TextFieldを利用します。
TextFieldに設定した各プロパティについて説明します。
controller:
TextFieldにて入力した文字列を参照するため、TextEditingControllerのインスタンス(=dateTextController
)を設定しています。
これでdateTextController.text
で入力した文字列を参照できます。
この実装はFlutterのCookbookを参考にしました。
decoration:
TextFieldに入力する値のヒントを表示させる設定をしています。
今回は、秒数を入力して欲しいので「sec」としました。
autofocus:
フォーカスを当てる設定です。
今回は、ダイアログ表示時に入力状態とするためフォーカスを当てる設定(= true)にしています。
keyboardType:
ソフトキーボードのタイプを設定します。
今回は、数字入力とするためTextInputType.number
を設定しています。 - actions
OK/キャンセルボタンを配置します。
各々のボタンはFlatButtonを利用します。
FlatButtonに設定した各プロパティについて説明します。
child:
ボタンのラベルを設定します。
MaterialLocalizationsに頻出するラベルは定義されているので利用すると便利です。
onPressed:
ボタン押下時の処理を設定します。
ダイアログを閉じるだけならば、Navigator.pop(context)
を利用します。
ダイアログを閉じて、さらに呼び出し元に値を返したい場合は、Navigator.pop(context, result)
のように、第二引数に結果を設定します。
今回は、dateTextController.text
でTextFieldに入力した文字列を取得し、Durationに変換した結果を返しています。
ダイアログを表示する
ダイアログの表示にあたっては、showDialogを利用します。showDialogの戻り値はFuture<T>ですが、これは Navigator.pop
で設定した値(今回の場合は制限時間)をFutureでラップしたデータとなります。
また、showDialogで設定が必要となる引数は次の通りです。
- BuildContext context
ダイアログ用のNavigatorとThemeを取得するために利用するようです。 - WidgetBuilder builder
ダイアログのWidgetを返す処理(Widget Function(BuildContext context)型)を設定します。
そして今回は、次のようにshowDialogを呼び出すshowTimerDialogを作成しています。showTimePickerを参考にしました。
ダイアログを呼び出す処理
ダイアログを呼び出す処理は次のように実装しています。
ダイアログからの戻り値を利用して、カウントダウンタイマーの制限時間をセットするようにBLoCを呼び出しています。
今回は、ダイアログで入力した値を呼び出し元の画面に渡す実装について紹介しました。
制限時間は秒数入力だけと使い勝手がいまいちなので、UIの改良ができればと思います。