I'm making a calendar using table_calendar
and I want to change the selected day.
I used setState
and it works, but doesn't change the selected day widget.
I'm not sure why it's happened.
My code:
import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
import 'dart:developer' as developer;
import '../widgets/table_calendar_util.dart';
class LessonBody extends StatefulWidget {
const LessonBody({super.key});
@override
State<LessonBody> createState() => _LessonBodyState();
}
class _LessonBodyState extends State<LessonBody> {
// Using a `LinkedHashSet` is recommended due to equality comparison override
final Set<DateTime> _selectedDays = LinkedHashSet<DateTime>(
equals: isSameDay,
hashCode: getHashCode,
);
CalendarFormat _calendarFormat = CalendarFormat.week;
DateTime _focusedDay = DateTime.now();
DateTime _selectedDay = DateTime.now();
Map<DateTime, List<Event>>? _noteMapByDay;
@override
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: [
Stack(
children: [
TableCalendar<Event>(
calendarStyle: const CalendarStyle(
todayDecoration: BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
),
markerDecoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.rectangle,
),
),
firstDay: kFirstDay,
lastDay: kLastDay,
focusedDay: _focusedDay,
calendarFormat: _calendarFormat,
eventLoader: (day) {
if (_noteMapByDay != null) {
return _noteMapByDay![day] ?? [];
} else {
return [];
}
},
startingDayOfWeek: StartingDayOfWeek.monday,
selectedDayPredicate: (day) {
// Use values from Set to mark multiple days as selected
return _selectedDays.contains(day);
},
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
developer.log('focusedDay : $_focusedDay');
developer.log('selectedDay : $_selectedDay');
});
developer.log('select');
},
onFormatChanged: (format) {
if (_calendarFormat != format) {
setState(() {
_calendarFormat = format;
developer.log('onFormatChanged : ${format.name}');
});
}
},
onPageChanged: (focusedDay) {
_focusedDay = focusedDay;
},
),
// 주, 2주, 월 단위로 보여주기
Positioned(
right: 60,
top: 9,
child: Align(
alignment: Alignment.topRight,
child: TextButton.icon(
onPressed: () {
setState(() {
switch (_calendarFormat) {
case CalendarFormat.week:
_calendarFormat = CalendarFormat.twoWeeks;
break;
case CalendarFormat.twoWeeks:
_calendarFormat = CalendarFormat.month;
break;
case CalendarFormat.month:
_calendarFormat = CalendarFormat.week;
break;
default:
}
});
},
icon: const Icon(
Icons.calendar_month_rounded,
color: Colors.green,
),
label: _calendarFormat == CalendarFormat.week
? const Text(
'주',
style: TextStyle(color: Colors.green),
)
: _calendarFormat == CalendarFormat.twoWeeks
? const Text(
'2주',
style: TextStyle(color: Colors.green),
)
: const Text(
'월',
style: TextStyle(color: Colors.green),
)),
),
),
],
),
const SizedBox(
height: 15,
),
],
),
);
}
}
Thank you for reading this.
CodePudding user response:
It looks like the problem is with the selectedDayPredicate
function in the TableCalendar
widget. You are using a LinkedHashSet
to keep track of selected days, but you are not updating it when the user selects a new day.
You can try adding the selected day to the set when the onDaySelected
callback is called:
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDays.add(selectedDay);
_selectedDay = selectedDay;
_focusedDay = focusedDay;
developer.log('focusedDay : $_focusedDay');
developer.log('selectedDay : $_selectedDay');
});
developer.log('select');
}