はじめに
ユアマイスター Advent Calendar 2019 の12日目の記事です。
ユアマイスターでは、 あなたのマイスター でハウスクリーニングや修理などのサービスを提供するプロや職人が利用する店舗向けアプリ「マイスターアプリ」 (Android版, iOS版) があります。
このアプリでは、Flutterを採用しており、2019年10月にリリースされました。(その他の技術スタックは こちら)
今回は、DatePickerを使ったTipsを紹介したいと思います。
基本
まず、DatePickerを使いたいときは showDatePicker
メソッドを使います。
これを使うと、日付選択できるダイアログが画面に立ち上がります。
class PickerDemoPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: IconButton(
icon: Icon(Icons.calendar_today),
onPressed: () async {
final selectedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(DateTime.now().year),
lastDate: DateTime(DateTime.now().year + 1),
);
if (selectedDate != null) {
// do something
}
},
),
),
);
}
}
これは、required となっている引数だけを使ったサンプルです。
簡単に説明すると、
-
initialDate
: はじめに選択されている日付 -
firstDate
: 選択可能な最小の日付 -
lastDate
: 選択可能な最大の日付
返ってきた値をNullチェックしているのは、キャンセルボタンやダイアログの外をタップしてダイアログを閉じたとき、Nullが返ってくるためです。
先に年を選択させる
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(DateTime.now().year),
lastDate: DateTime(DateTime.now().year + 6),
initialDatePickerMode: DatePickerMode.year,
);
initialDatePickerMode
を DatePickerMode.year
にすると、年選択 -> 月日選択ができるようになります。
生年月日を選択するときなどに使えます。
指定した日を選択できないようにする
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(DateTime.now().year),
lastDate: DateTime(DateTime.now().year + 6),
selectableDayPredicate: (DateTime date) =>
date.weekday == 6 || date.weekday == 7 ? false : true,
);
selectableDayPredicate
を false にすることで、特定の日を選択できないようにできます。
ただし、initialDate
で初期選択に選んだ日は選択された状態で表示されるので、少し注意が必要です。
上記のサンプルは、平日のみ選択可能にしたものです。
日本語化する
まず、Flutterを多言語対応する必要があります。
これからざっと書いていきますが、
詳しく知りたい方は、以下の公式ドキュメントを見てください。
flutter_localizations パッケージをインストール
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
pubspec.yaml に追加したあとは、 flutter pub get
のコマンドでインストール。
アプリが対応する言語のロケールを指定する
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
const Locale('en'),
const Locale('ja'),
],
// ...
)
インストールした flutter_localizations
をimportして、 MaterialAppに localizationsDelegates
と supportedLocales
を設定。
showDatePicker() でロケールを設定する
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(DateTime.now().year),
lastDate: DateTime(DateTime.now().year + 6),
locale: const Locale('ja'),
);
これで、 ”xxxx年xx月xx日” というフォーマットで表示されます。
DatePickerの色を変える
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(DateTime.now().year),
lastDate: DateTime(DateTime.now().year + 6),
builder: (BuildContext context, Widget child) {
return Theme(
data: ThemeData(
// ヘッダーの色
primaryColor: Colors.red,
// 日付選択部の色
dialogBackgroundColor: Colors.green,
// 選択されたときのテキストの色
accentTextTheme: TextTheme(
body2: TextStyle(
color: Colors.black,
),
),
// 選択されたときの円の色
accentColor: Colors.purple,
// OK/CANCELボタンのテキストの色
buttonTheme: const ButtonThemeData(
textTheme: ButtonTextTheme.accent,
),
),
child: child,
);
},
);
基本的には、MaterialApp で設定されたThemeでDatePickerの色が決まりますが、 上記の方法でDatePickerの色をカスタマイズできます。
ダイアログでなく、画面にDatePickerを埋め込みたい
現状、DatePickerを画面内に表示するものは提供されていませんでした。
少し探してみたところ、flutter_date_pickers があったので、それを使ってみてもいいかもしれません。
まとめ
最後に、これまで紹介したコードのまとめたものを残しておきます。
final selectedDate = await showDatePicker(
context: context,
// 初期選択されている日付
initialDate: DateTime.now(),
// 選択可能な最小の日付
firstDate: DateTime(DateTime.now().year),
// 選択可能な最大の日付
lastDate: DateTime(DateTime.now().year + 6),
// 日付の選択形式
initialDatePickerMode: DatePickerMode.year,
// 指定した日を選択できないようにする
selectableDayPredicate: (DateTime date) =>
date.weekday == 6 || date.weekday == 7 ? false : true,
// 日本語化
locale: const Locale('ja'),
// DatePickerの色を変える
builder: (BuildContext context, Widget child) {
return Theme(
data: ThemeData(
// ヘッダーの色
primaryColor: Colors.red,
// 日付選択部の色
dialogBackgroundColor: Colors.green,
// 選択されたときのテキストの色
accentTextTheme: TextTheme(
body2: TextStyle(
color: Colors.black,
),
),
// 選択されたときの円の色
accentColor: Colors.purple,
// OK/CANCELボタンのテキストの色
buttonTheme: const ButtonThemeData(
textTheme: ButtonTextTheme.accent,
),
),
child: child,
);
},
);
// キャンセルボタンやダイアログの外をタップしてダイアログを閉じたとき、NULLが返ってくる
if (selectedDate != null) {
// do something
}