【Flutter】DatetimePicker の使い方

##  初めに
DatetimePicker とは、以下の画像のようにユーザに年月日を入力してもらうための Widget です。
生年月日の選択などに使用されます。
<img width=250, src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609901/bd169f12-651b-6956-21c7-c93e13cc5478.png">

## 準備
まずは、[DatetimePicker パッケージ](https://pub.dev/packages/flutter_datetime_picker) を「 pubspeck.yaml 」に記述します。
パッケージのバージョンは、特に制約がなければ最新のバージョンで問題ありません。

```yaml: pubspeck.yaml
dependencies:
  flutter:
    sdk: flutter

  flutter_datetime_picker: ^1.5.1
```
Pub get をして準備は完了です。

## 実装
まずは実装したい画面で DatetimePicker をインポートします。
```dart: main.dart
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
```
<br>

以下のコードは、 onPressed に DatetimePicker を表示させる処理を記述した TextButton です。
このように、 DatetimePicker は常時表示されるのではなく、ユーザのアクションによって表示されます。

```dart: main.dart
TextButton(
  onPressed: () {
    DatePicker.showDatePicker(context,
      showTitleActions: true,
      minTime: DateTime(1950, 1, 1),
      maxTime: DateTime(2022, 8, 17),
      onChanged: (date) {
        print('change $date');
      },
      onConfirm: (date) {
        print('confirm $date');
      },
      currentTime: DateTime.now(),
      locale: LocaleType.jp
    );
  },
  child: const Text(
    '生年月日を選択',
    style: TextStyle(color: Colors.blue),
  ),
),
```

### showTitleActions
showTitleActions は以下の画像の「キャンセル」「完了」ボタンを表示させるプロパティです。
<img width=250, src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609901/bd169f12-651b-6956-21c7-c93e13cc5478.png">
デフォルトでは true になっています。
false に指定すると、以下のように「キャンセル」「完了」ボタンが表示されなくなります。
<img width=250, src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609901/300615f0-972c-6163-6b31-cafd21e36634.png">

### minTime
minTime では DatetimePicker で指定できる最も過去の日時、最小の日時を指定します。
上のコードでは 1950年1月1日に指定されています。

### maxTime
maxTime では DatetimePicker で指定できる最も最近の日時、最大の日時を指定します。
上のコードでは 2022年8月17日に指定されています。

### onChanged
onChanged では DatetimePicker の日時が変更された際の処理を記述します。
TextField の onChanged と似たプロパティです。
ユーザが完了ボタンを押していない場合でも、 その変更が onChanged として読み取られます。

上のコードでは変更された日時を引数として受け取り、コンソールに表示するようにしています。

### onConfirm
onConfirm　ではユーザが完了ボタンを押した際の処理を記述します。
TextField の onSubmitted と似たプロパティです。

上のコードでは完了ボタンが押された際の日時を引数として受け取り、それをコンソールに表示しています。

### currentTime
currentTime はDatetimePicker の初期値の日時を指定するためのプロパティです。
上のコードでは `DateTime.now()` を指定することで、現在の日時を初期値に指定しています。

### locale
locale は DatetimePicker の言語設定をするためのプロパティです。
上のコードでは `LocaleType.jp` と指定することで日本語の設定にしています。

## Datetime を取得する

次はユーザが変更した Datetime を変数に代入して取得しましょう。

全体コードは以下の通りです。
```dart: main.dart
import 'package:flutter/material.dart';
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final birthdayProvider = StateProvider<DateTime>((ref) => DateTime.now());

class DatetimePickerExample extends ConsumerWidget {
  const DatetimePickerExample({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final birthdayNotifier = ref.watch(birthdayProvider.notifier);
    final birthday = ref.watch(birthdayProvider);
    return Scaffold(
      appBar: AppBar(
        title: const Text("DatetimePickerExample"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
              onPressed: () {
                DatePicker.showDatePicker(context,
                  showTitleActions: true,
                  minTime: DateTime(1950, 1, 1),
                  maxTime: DateTime(2022, 8, 17),
                  onChanged: (date) {
                    print('change $date');
                    birthdayNotifier.state = date;
                  },
                  onConfirm: (date) {
                    print('confirm $date');
                    birthdayNotifier.state = date;
                  },
                  currentTime: DateTime.now(), locale: LocaleType.jp
                );
              },
              child: const Text(
                '生年月日を選択',
                style: TextStyle(color: Colors.blue),
              ),
            ),
            Text("${birthday.year}年${birthday.month}月${birthday.day}日")
          ],
        ),
      ),
    );
  }
}
```
<br>

```dart: main.dart
final birthdayProvider = StateProvider<DateTime>((ref) => DateTime.now());
```
このコードでは DateTime 型の変数の状態を監視するための StateProvider を作成し、 `birthdayProvider`という変数に代入しています。
また、初期値は現在の日時に指定しています。
<br>

```dart: main.dart
final birthdayNotifier = ref.watch(birthdayProvider.notifier);
final birthday = ref.watch(birthdayProvider);
```
このコードでは先ほど作成した birthdayProvider を読み取った値をそれぞれ `birthdayNotifier` `birthday` という変数に代入しています。
<br>

```dart: main.dart
onChanged: (date) {
  print('change $date');
  birthdayNotifier.state = date;
},
onConfirm: (date) {
  print('confirm $date');
  birthdayNotifier.state = date;
},
```
このコードで、それぞれ onChanged と onConfirm で引数として受け取った `date` という変数の値を、先ほど作成した `birthdayProvider` を読み取った値の変数に代入しています。

こうすることで、ユーザが変更した日時の変更が `birthdayProvider` に反映されます。

```dart: main.dart
Text("${birthday.year}年${birthday.month}月${birthday.day}日")
```
このコードでは `birthdayProvider` の内容を読み取った値を Text として表示させています。
こうすることで、変更された日時を受け取ることができるようになりました。

## あとがき
最後まで読んでいただきありがとうございました。


以上です。

参考にしていただければ幸いです。
誤っている箇所があればご指摘いただければ幸いです。

### 参考にしたサイト
https://pub.dev/packages/flutter_datetime_picker