はじめに
Flutterでカレンダーを表示したいときによく使うのがtable_calendar
かと思います。
ただ、月を移動した後今日の日付に戻るためには、移動した月分操作しなければならず、少しめんどくさく感じるためUIをカスタムし当日へ戻るボタンをつけました。(ドキュメントで探しましたが、ないはず…あったらすみません…)
まずカレンダーを準備
サッとtabel_calendar を準備します。この辺はpub.devに載ってるので簡潔に。
$ flutter pub add table_calendar
とりあえず始まりと最後を現在から前後2ヶ月に設定。
final _today = Datetime.now();
final _firstDay = DateTime(today.year, today.month - 2, 1);
final _lastDay = DateTime(today.year, today.month + 3, 0);
DateTime _focusedDay = _today;
カレンダーのウィジェットを作成。
TableCalendar(
locale: 'ja_JP',
firstDay: _firstDay,
lastDay: _lastDay,
focusedDay: _focusedDay,
// この設定で月を移動した時にヘッダーの表示が移動先の月になる
onPageChanged: (focusedDay) {
_focusedDay = focusedDay;
}
// 月曜日始まりにしたいときは入れる
startDayOfWeek: StartingDayOfWeek.monday,
)
Headerのカスタム
table_calendarのUIをカスタムできるcalendarBuilders
を使用します。
TableCalendar(
locale: 'ja_JP',
firstDay: _firstDay,
lastDay: _lastDay,
focusedDay: _focusedDay,
onPageChanged: (focusedDay) {
_focusedDay = focusedDay;
}
startingDayOfWeek: StartingDayOfWeek.monday,
// 以下からカスタム内容
calendarBuilders: CalendarBuilders(
// headerのカスタム
headerTitleBuilder: (_, day) {
final DateFormat dateFormat = DateFormat('yyyy年M月');
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(dateFormat.format(_focusedDay), style: const TextStyle(fontSize: 16)),
TextButton(
onPressed: () {
setState(() {
_focusedDay = DateTime.now();
})
},
child: const Text('今日')
)
]
);
}
)
)
ヘッダー部分のカスタムは、headerTitleBulder
を使用します。
デフォルトのヘッダーのスタイルを踏襲してyyyy年M月
の形にしています。
Text部分は_focusedDay
を入れることで、先月や来月に移動した際、表示を移動した先の月に変更できます。
横並びでTextButton を配置し、タップしたら_focusedDay
を今日に変更します。
これで当日に戻る機能が実装されました。
おまけ
見やすいように土日の色を変える
デフォルトでは曜日が全部灰色ですが、指定した曜日だけ色を変更できたりもします。
calendarBuilders: CalendarBuilders(
headerTitleBuilder: (_, day) {
final DateFormat dateFormatForMonth = DateFormat('yyyy年M月');
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(dateFormatForMonth.format(_focusedDay), style: const TextStyle(fontSize: 16),),
TextButton(
onPressed: () {
setState(() {
_selectedDay = DateTime.now();
_focusedDay = DateTime.now();
});
},
child: const Text('今日')
),
],
);
},
// 以下追加。土日だけ色を変更する。
dowBuilder: (_, day) {
final text = DateFormat.E('ja').format(day);
if (day.weekday == DateTime.sunday) {
return Center(
child: Text(text, style: const TextStyle(color: Colors.red, fontWeight: FontWeight.bold)),
);
} else if (day.weekday == DateTime.saturday) {
return Center(
child: Text(
text,
style: const TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
),
);
}
return null;
})