Flutterでカレンダーを使用してアプリを作る際に便利なパッケージとしてTableCalendarがあります。
今回は、Flutterでカレンダーを作成するのに王道なtable_calendarを使った実装を解説していきたいと思います。(2023.02現在)
今回使用したバージョンは下記の通りです。
Flutter 3.0.5
Dart 2.17.6
table_calendar: 3.0.9
対象の読書
- FlutterでTableCalendarを使用してアプリを作りたい人
- TableCalendarの基本的な使い方を知りたい人
パッケージのインストール
まずは、どのパッケージでもお馴染みのpubspec.yamlファイルに設定を書き込みんで「flutter pub get」コマンドを実行します。
environment:
sdk: ">=2.17.6 <3.0.0"
dependencies:
flutter:
sdk: flutter
table_calendar: ^3.0.9
カレンダーの表示
まずはシンプルなカレンダーを表示します。
以下の実装でカレンダーの表示が可能です。
focesedDayは今日に日付に印がつきます。
DateTime _focusedDay = DateTime.now();
TableCalendar(
firstDay: DateTime.utc(2023, 1, 1),
lastDay: DateTime.utc(2024, 12, 31),
focusedDay: _focusedDay,
);
カレンダーフォーマット
次にカレンダーの表示を「1週間、2週間、1ヶ月」と3つに変更できるように実装します。
デフォルトを1ヶ月の表示に設定しています。
CalendarFormat _calendarFormat = CalendarFormat.month; // 月フォーマット
onFormatChanged: (format) { // 「月」「週」変更
if (_calendarFormat != format) {
setState(() {
_calendarFormat = format;
});
}
}
日付の選択
selectedDayPredicate:を使用してどの日が現在選択されているかを設定します。
今回はisSameDay関数を返す実装にしています。
isSameDayは2つの引数(DateTime)を取り、2つの日付が同じか否かを判定します。
DateTime? _selectedDay; // 選択している日付
// 選択日のアニメーション
selectedDayPredicate: (day) {
return isSameDay(_selectedDay, day);
},
加えてももう一つ下記の実装が必要になります。
// 日付が選択されたときの処理
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
});
}
onDaySelected はカレンダーがタップされるたびに呼ばれる関数で、そこにタップした際の日付(_selectedDay)を設定します。
イベントドットの表示
ここからは少しだけ応用です。
自分がドットマークをつけたい日付を宣言し、eventLoaderに返してあげればドットが表示されます。
//Map形式で保持 keyが日付 値が文字列
final sampleMap = {
DateTime.utc(2023, 2,20): ['firstEvent', 'secondEvent'],
DateTime.utc(2023, 2,5): ['thirdEvent', 'fourthEvent'],
};
eventLoader: (date) { // イベントドット処理
return sampleMap2024/11/10 ?? []
},
イベントの表示
さらにイベントをTextなどに表示したい場合も少し触れます。
Textなどに表示したい日付を宣言し_selectedEventsに代入してあげれば可能です。
List<String> _selectedEvents = [];
final sampleEvents = {
DateTime.utc(2023, 2,20): ['firstEvent', 'secondEvent'],
DateTime.utc(2023, 2,5): ['thirdEvent', 'fourthEvent']
};
// 日付が選択されたときの処理
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
_selectedEvents = sampleEvents[selectedDay] ?? []; // ココを追加
});
}
あとは、_selectedEventsに格納されたものを好きなものに表示させればOKです。
今回はListTileに表示させます。
// タップした時表示するリスト
Expanded(
child: ListView.builder(
itemCount: _selectedEvents.length,
itemBuilder: (context, index) {
final event = _selectedEvents[index];
return Card(
child: ListTile(
title: Text(event),
),
);
},
),
),
全体のコード
全体のコードはこちらになります。
import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
class CalenderPage extends StatefulWidget {
const CalenderPage({Key? key}) : super(key: key);
@override
State<CalenderPage> createState() => _CalenderPageState();
}
class _CalenderPageState extends State<CalenderPage> {
DateTime _focusedDay = DateTime.now(); // 現在日
CalendarFormat _calendarFormat = CalendarFormat.month; // 月フォーマット
DateTime? _selectedDay; // 選択している日付
List<String> _selectedEvents = [];
//Map形式で保持 keyが日付 値が文字列
final sampleMap = {
DateTime.utc(2023, 2,20): ['firstEvent', 'secondEvent'],
DateTime.utc(2023, 2,5): ['thirdEvent', 'fourthEvent'],
};
final sampleEvents = {
DateTime.utc(2023, 2,20): ['firstEvent', 'secondEvent'],
DateTime.utc(2023, 2,5): ['thirdEvent', 'fourthEvent']
};
@override
Widget build(BuildContext context) {
return Scaffold(
// カレンダーUI実装
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: TableCalendar(
firstDay: DateTime.utc(2023, 1, 1),
lastDay: DateTime.utc(2024, 12, 31),
focusedDay: _focusedDay,
eventLoader: (date) { // イベントドット処理
return sampleMap2024/11/10 ?? [];
},
calendarFormat: _calendarFormat, // デフォを月表示に設定
onFormatChanged: (format) { // 「月」「週」変更
if (_calendarFormat != format) {
setState(() {
_calendarFormat = format;
});
}
},
// 選択日のアニメーション
selectedDayPredicate: (day) {
return isSameDay(_selectedDay, day);
},
// 日付が選択されたときの処理
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
_selectedEvents = sampleEvents[selectedDay] ?? [];
});
}
),
),
// タップした時表示するリスト
Expanded(
child: ListView.builder(
itemCount: _selectedEvents.length,
itemBuilder: (context, index) {
final event = _selectedEvents[index];
return Card(
child: ListTile(
title: Text(event),
),
);
},
),
),
],
),
);
}
}
公式パッケージ
なるべく最新のものを使用する方がベターだと思います。
最後に
シンプルなカレンダーをtable_calendarを使用して実装してみました。
他にもいろんな機能があるのでぜひ試してみてください。
どなたかのご参考になれば幸いです。
ではまた。
コメント