カレンダーで年と月だけを選択したい
Flutter で日付を入力するときにカレンダーから選択できるウィジェット(DatePicker
)があります。これを使うとマテリアルデザインのカレンダーが表示されて、そこから日付を選択する形で入力ができるようになります。
// DatePickerの仕様イメージ
selectDate(BuildContext context) async {
// 1年前から1年後の範囲でカレンダーから日付を選択します。
var selectedDate = await showDatePicker(
context: context,
initialDate: this.date,
firstDate: DateTime(DateTime.now().year - 1),
lastDate: DateTime(DateTime.now().year + 1),
);
// 選択がキャンセルされた場合はNULL
if (selectedDate == null) return;
// 選択されて日付で更新
this.setState(() {
this.date = selectedDate;
});
}
便利なカレンダーウィジェットですが、これを年月だけから選択することができません。もし年と月だけの入力が必要で日付の入力は不要といった場合にはこの DatePicker
ではとても不便です。
いい感じのマテリアルデザインカレンダーから年月だけを選択して日付が表示されないようにするために month_picker_dialog
というパッケージを紹介します。
month_picker_dialog
を使用すると以下のようなカレンダーから選択することができるようになります。
month_picker_dialog の使い方
month_picker_dialog | Flutter Package
month_picker_dialog
はマテリアルデザインで構成されたカレンダーから年月を指定する形で入力ができるようなダイアログを表示するパッケージです。国際化対応もされているので日本語でのカレンダー表示にも対応しており便利です。
使い方もほとんど DatePicker
と同じ感じです。
パッケージを追加する
まず month_picker_dialog
で表示するカレンダーを日本語にするために、Flutterアプリを国際化対応が必要です。
Internationalizing Flutter apps – Flutter
基本は上のページの手順に沿って進めます。
まず、pubspec.yaml
に以下の3行追加します。
dependencies:
flutter:
sdk: flutter
flutter_localizations: # 行追加
sdk: flutter # 行追加
month_picker_dialog: ^0.3.3 # 行追加
flutter_localizations
の箇所が国際化対応のパッケージで、あとは今回使用する month_picker_dialog
を追加しています。バージョンは適当に最新を使えばよいです。
ファイル更新後、pub get packages
を実行してパッケージを更新しておきます。
日本語化の対応を MaterialApp に設定する
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('ja'),
],
home: HomePage(),
);
}
}
MaterialApp
に localizationsDelegates
と supportedLocales
を上の通り設定します。
これで準備完了です。あとは HomePage
にカレンダーから選択する処理を実装していきます。
カレンダーから年月を選択する
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
DateTime date = DateTime.now();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('MonthPicker Sample')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(this.date.toString(), style: TextStyle(fontSize: 32)),
RaisedButton(
child: Text('選択'),
onPressed: () => this.selectDate(context),
),
],
),
),
);
}
selectDate(BuildContext context) async {
// 1年前から1年後の範囲でカレンダーから日付を選択します。
var selectedDate = await showMonthPicker(
context: context,
initialDate: this.date,
firstDate: DateTime(DateTime.now().year - 1),
lastDate: DateTime(DateTime.now().year + 1),
);
// 選択がキャンセルされた場合はNULL
if (selectedDate == null) return;
// 選択されて日付で更新
this.setState(() {
this.date = selectedDate;
});
}
}
ボタンとテキストを用意しただけの簡単なUIで、ボタンを押下するとカレンダーが表示されます。カレンダーは年と月を選択できます。日付は選択できません。
カレンダーは showMonthPicker
という関数を実行すれば表示されます。引数は DatePicker
の showDatePicker
と同じようになっています。
選択結果は Future<DateTime>
で得られるので await
してから使います。選択結果に日付は年月は選択した値で日付は1日固定となります。
以下動作イメージです。
Flutter Web で動かしていますがもちろんモバイル端末上でも同じように動きます。
ちなみに日付も選ぶ普通のカレンダーにしたければ showMonthPicker
を showDatePicker
に変更すれば引数は同じで動作させられます。
日付を選択せず年月だけを選択できるマテリアルデザインのカレンダーを表示するパッケージの紹介でした。
以上。
記事を参考にさせていただきました。
カレンダーは表示されるのですが、私の環境では以下に記載されているのと同じ事象が起きています。
https://github.com/hmkrivoj/month_picker_dialog/issues/33
貴殿の環境では上記のような問題は発生しませんか?
もし回避方法をご存じでしたらご教示ください。