FlutterではTimePicker
を呼び出すことで簡単に時刻設定機能を導入することが可能です。
早速試してみましょう。サンプルコードはこちらです。
import 'package:flutter/material.dart';void main() { runApp(const MyApp());}class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override _MyAppState createState() => _MyAppState();}class _MyAppState extends State<MyApp> { TimeOfDay? _selectedTime; @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: Builder(builder: (context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ _selectedTime == null ? const Text( '時間を選択してください', style: TextStyle(fontSize: 30.0), ) : Text( '${_selectedTime!.hour.toString()}:${_selectedTime!.minute.toString()}', style: const TextStyle(fontSize: 40.0), ), const SizedBox( height: 40.0, ), ElevatedButton( onPressed: () { _selectTime(context); }, child: const Text( '選択する', style: TextStyle(fontSize: 30.0), ), ) ], ), ), ); })); } Future _selectTime(BuildContext context) async { final int selectedHour = _selectedTime?.hour ?? 9; final int selectedMinute = _selectedTime?.minute ?? 30; final initialTime = TimeOfDay(hour: selectedHour, minute: selectedMinute); final time = await showTimePicker( context: context, initialTime: initialTime, ); if (time != null) { setState(() => _selectedTime = time); } else { return; } }}
アプリを起動して、「選択する」ボタンを押すとTimePicker
が出現します。
そこで任意の時刻を設定して「OK」を押すと、TimePicker
が閉じてテキスト部分に選択した時刻が反映されるようにしています。
今回、選択した時刻を状態として保持しておきたいため、StateFullWidget
の中にTimePicker
に関連するコードを書いています。
以下のように15行目で状態保持用の変数を設定しています。
class _MyAppState extends State<MyApp> { TimeOfDay? _selectedTime; @override Widget build(BuildContext context) {
TimeOfDay
はFlutter標準、時刻用の型です。
この_selectedTime
にユーザーが選択した時刻情報を保持するようにします。
ボタンを押した時のコードを見ていきましょう。
以下のコードを見てください。
ElevatedButton( onPressed: () { _selectTime(context); }, child: const Text( '選択する', style: TextStyle(fontSize: 30.0), ), )
onPressed:
にボタンを押した時の処理を書いています。
今回は_selectTime
ひとつだけです。このメソッドはlib/main.dart
の下部で定義しています。
以下のコードを見てください。
Future _selectTime(BuildContext context) async { final int selectedHour = _selectedTime?.hour ?? 9; final int selectedMinute = _selectedTime?.minute ?? 30; final initialTime = TimeOfDay(hour: selectedHour, minute: selectedMinute); final time = await showTimePicker( context: context, initialTime: initialTime, ); if (time != null) { setState(() => _selectedTime = time); } else { return; } }
この59行目から始まるメソッドが今回の心臓部ですね。
64行目でshowTimePicker
を実行しています。ここを通るとTimePicker
が画面に出現します。
今回引数にはinitialTime
を設定しています。ここには最初にTimePicker
上で選択している時刻を指定します。
60行目、61行目でやっているようにもし_selectedTime
にすでに時刻が設定されている(= 以前に選択している)場合はそちらを初期表示に使用しています。もし_selectedTime
に何も設定されていないときはデフォルト値として09:30の値が設定されるようにしています。
そしてTimePicker
が閉じられると69行目以降の処理が走り出します。
ここで「OK」ボタンをユーザーが押したときはtime
の変数に新しく選択した時刻情報が格納されています。
これを70行目のように_selectedTime
に設定しています。
一方でキャンセルボタンを押したなどで何も変更がなかったときは何もせずにreturn
で終了していることがわかります。
こうして得られた時刻は文字列として画面に表示されます。
少し上に戻ります。以下のコードを見てください。
child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ _selectedTime == null ? const Text( '時間を選択してください', style: TextStyle(fontSize: 30.0), ) : Text( '${_selectedTime!.hour.toString()}:${_selectedTime!.minute.toString()}', style: const TextStyle(fontSize: 40.0), ),
31行目で_selectedTime
の値の有無を基準にして表示内容を切り分けしています。TimePicker
で時刻が設定された後は、36行目以降が有効になります。
ここでは_selectedTime
の情報を文字列として展開しています。DropdownButton
などを使って自力で時刻設定用のUIを作ることもできますが結構手間がかかります。
思わぬ不具合も発生することも考慮すると、既にある部品を採用することを考えてみてもいいかもしれません。