[Flutter/dart] カレンダーに日付と一緒にアイコンも表示したい
概要
アプリを作っていると、カレンダーを使う場面は多いかと思います。そんな中でも、カレンダーの日付と一緒にアイコン画像を表示したい場合があります。例えばその日の勉強時間を記録したり、デート相手の写真を表示したり、、、などです。
flutterにもカレンダーを表示するライブラリは多々ありますが、日付と他の要素を表示できるのはflutter_calendar_carouselというものです。今回はflutter_calendar_carouselの使い方を紹介します。
使い方
まずはライブラリをインストールします。pubsec.yamlに以下を追加してください。
dependencies:
flutter_calendar_carousel: ^1.5.1
また、使用するモジュールの冒頭で以下のようにimportしてください。
import 'package:flutter_calendar_carousel/flutter_calendar_carousel.dart';
import 'package:flutter_calendar_carousel/classes/event.dart';
全体像
最初に全体像をお見せします。(StatefulWidgetのStateのbuild()メソッドです)
@override
Widget build(BuildContext context) {
List<DateTime> _days=[DateTime(2020, 12, 20), DateTime(2020, 12, 21)]; //アイコンを表示する日
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
margin: const EdgeInsets.only(top:20, left:20),
//ここから
child: CalendarCarousel<Event>(
//アイコンを表示する日付について、EventのList
markedDatesMap: _getMarkedDateMap(_days, context),
markedDateShowIcon: true,
markedDateIconMaxShown: 1,
markedDateMoreShowTotal: null,
markedDateIconBuilder: (event)=>event.icon, //アイコン
),
)
);
}
Eventは日付とアイコンをまとめたクラスです。
class Event implements EventInterface {
final DateTime date;
final String title;
final Widget icon;
final Widget dot;
//以下略
markedDateMap: プロパティにEventのListを渡し、markedDateIconBulder:でEventに登録されたアイコンを表示させます。
Event Listの作成
_getMarkedDateMap()はアイコンを表示する日付のListからEventのListを作ります。
EventList<Event> _getMarkedDateMap(List<DateTime> days, BuildContext context){
EventList<Event> _markedDateMap=new EventList<Event>(events: {});
for (DateTime _date in days){
_markedDateMap.add(_date,
new Event(
date: _date,
icon: _getIcon(_date), //アイコンを作成
));
}
return _markedDateMap;
}
各日付に対し、Eventコンストラクタに日付と日付に紐づいたアイコンを作成します。
日付に紐づいたアイコンの作成
日付を引数に取って表示するアイコンを作成するメソッドが_getIcon()です。
ここで注意しなければいけないのは、アイコンだけでなく、日付の文字も明示的に表示してあげる必要があることです。(アイコンを表示する時点で上書きしてしまうみたいです)
Widget _getIcon(DateTime date){
bool _isToday=isSameDay(date, DateTime.now()); //今日?
CalendarCarousel _calendar_default=CalendarCarousel();
Color _today_col=_calendar_default.todayButtonColor; //今日の背景色
return Container(
decoration: new BoxDecoration(
color: _isToday ? _today_col : Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(1000),
), //今日の場合は赤の円の背景 それ以外は無し
child: Column(
children: [
Text(
date.day.toString(),
style: TextStyle(
color: _isToday? Colors.white: getDayCol(date),
fontWeight: FontWeight.w400
), //日付の文字 今日は白、それ以外は平日黒、休日赤
),
SizedBox(height: 2,),
Icon(
Icons.brightness_1,
color: Colors.blue,
size: 16,
), //日付と一緒に表示するアイコン
]
)
);
}
まず、今日の場合は背景が赤の円形になります。また、日付の色も今日ならば白、それ以外は平日は黒、休日は赤にします。(こういう設定もアイコンで上書きする時点で消えてしまうみたいです)
Icon()の部分が本題の、日付と一緒に表示したいアイコンです。適宜置き換えてください。
与えられた日付が今日か判定するため以下のメソッドを使っています。
static bool isSameDay(DateTime day1, DateTime day2) {
return ((day1.difference(day2).inDays) == 0 && (day1.day == day2.day));
}
また、与えられた日付が平日か休日かを判定し、対応する文字色を返すメソッドを使っています。(祝日とかは対応してないので必要ならば追加してください)
Color getDayCol(DateTime _date){
switch(_date.weekday){
case DateTime.saturday:
case DateTime.sunday:
return Colors.red;
default:
return Colors.black;
}
}
以上で以下のようなカレンダーが表示されます。
最後に
あまり大きいwidgetは表示できないので注意しましょう。また、日付文字についての設定をやり直さないといけないのが結構面倒です。
最新記事
すべて表示やりたいこと TextFieldで入力フォームを作りたい。 例えば入力内容が金額の場合、3桁区切りで頭に¥を付けた表記にしたい。 ただしユーザにこれらを入力させるのではなく、ユーザはあくまで数字を入力するだけで、アプリ側で自動でフォーマットしたい。 方法...
現象 やってること iosシミュレータで画像をデバイスのローカルに保存 保存したパスをデータベースに保存 アプリ立ち上げ時にデータベースから画像パスを取得し、そのパスの画像を画面上に表示 起きている現象 iosシミュレータを再起動した場合、上記3で「ファイルパスが見つからな...
やりたいこと 初期値さえ決まればあとは不変な変数がある ただし、コンストラクタ起動時にはまだ決定できない このような変数について late finalで変数を定義 (何らかのタイミングで)初期化されたかどうかをチェックし、されていなければ値を入れる(チェックしないとfina...
Comments