Change color of currently selected day in CompactMonthTimetable
Opened this issue · 18 comments
How can currently selected date in CompactMonthTimetable be changed?
In a way so that today date is always selected in its own colour (as it is now which is good), but for those manually selected dates in CompactMonthTimetable to set some custom color?
If you already customize the dateBuilder
of MonthWidget
, you can customize/overwrite the style for each DateIndicator
individually. Alternatively, you can customize the themeData.dateIndicatorStyleProvider
and return the style you want for each day.
@JonasWanke I will try it tomorrow morning with customized dateBuilder
.
I have one more question related to dateBuilder style, when i applied custom dateBuilder
i noticed dates from other months are not displayed in MonthWidget
(neither as "enabled" or "disabled"), but only dates from currently displayed month are shown? For details i will post screenshot and code tomorrow morning
What i would like is to show dates from other months in a light grey color just as they are currently in default settings ( although if you notice image above in first post here (default display) you will see that dates that are before "today" date are in different color compared to those dates that are after "today" date, as if they are lighter color, and disabled dates are even lighter but that is good about disabled dates. Is that default style or i have perhaps done something wrong?
Have a look at monthWidgetStyle.showDatesFromOtherMonths
and monthWidgetStyle.showDatesFromOtherMonthsAsDisabled
, which are used here:
timetable/lib/src/components/month_widget.dart
Lines 45 to 63 in 9405c9c
@JonasWanke I'm trying handle MonthWidget
now and I run into few issues that i'm trying to solve:
- FIRST ISSUE:
I'm not sure how to define color for currently selected date, as you suggested I tried to usedateIndicatorStyleProvider
but I have to select date 2 times in order for changes to be applied visually, here is a short clip:
dates.issue.mp4
CODE:
dateIndicatorStyleProvider: (date) => DateIndicatorStyle(
context,
date,
textStyle: TextStyle(color: _dateController.date.value == date ? Colors.white : Colors.black),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _dateController.date.value == date ? Colors.red : Colors.transparent
),
),
- SECOND ISSUE:
I have navigated to January 2022, and there only 30 dates appears when it should be 31. I have also noticed same issue with February 2022 where it shows only 27 days instead of 28:
Regarding the first issue: Is the underlying Date controller updated and only that part of the UI isn't updated? It might be a problem with your state management: You have to rebuild the widget for it to know that the lambda will return a different value.
Regarding the second issue: Please file a separate issue for that. If the problem isn't reproducible, please also include the relevant subset of your code.
Is the underlying Date controller updated and only that part of the UI isn't updated?
I haven't done my own coding here, I have tried to use what I already have and I see there is a setState
in onDateTap callback (in _updateVisibleDateRange
method):
child: Builder(builder: (context) {
return DefaultTimetableCallbacks(
callbacks: DefaultTimetableCallbacks.of(context)!.copyWith(
onDateTap: (date) {
_dateController.animateTo(date, vsync: this);
_updateVisibleDateRange(PredefinedVisibleDateRange.day);
},
),
where _updateVisibleDateRange
is:
void _updateVisibleDateRange(PredefinedVisibleDateRange newValue) {
setState(() {
_visibleDateRange = newValue;
_dateController.visibleRange = newValue.visibleDateRange;
});
_dateController.animateTo
changes the value asynchronously. You can try to call setState
after the animation is done
@JonasWanke I have tried this way and it did worked:
onDateTap: (date) {
_dateController.animateTo(date, vsync: this).then(
(value) => _updateVisibleDateRange(
PredefinedVisibleDateRange.day),
);
},
Recording.18.mp4
It does work but it changes only when animation completes with delay (does not feel natural as it is with other calendars). Is there any way to make it so that it instantly changes style for newly selected date?
You could use a separate DateController
for that on which you call jump instead of animate. Alternatively, change the focus date and compare to it in the lambda you pass to the style.
focus date and compare to it in the lambda you pass to the style.
What would be focus date and how could i change it? And in this case with focus date i would not have to use .then
function to change focus date after animation completes?
onDateTap: (date) {
_dateController.animateTo(date, vsync: this).then(
(value) => _updateVisibleDateRange(
PredefinedVisibleDateRange.day),
);
},
A separate field next to the controller that you always set to the date that should be highlighted.
Exactly. Just set it synchronously before or after calling animate and then call setState
synchronously as well
A separate field next to the controller that you always set to the date that should be highlighted
Which separate field? Isn't is from a function _updateVisibleDateRange
? I do not understand how exactly is selected date highligted
void _updateVisibleDateRange(PredefinedVisibleDateRange newValue) {
setState(() {
_visibleDateRange = newValue;
_dateController.visibleRange = newValue.visibleDateRange;
});
}
According to #100 (comment), you do the highlighting yourself. Instead of basing that on _dateController.date.value
, you can create a separate field for storing the date that should be displayed as selected
_dateController.date.value
oh a regular state value, thank you I tried and it works!
timetable/lib/src/components/month_widget.dart
I have removed themeMode: overrideState.themeMode
from Material App and I use my own theme, and now i'm trying to override CompactMonthTimetable
's MonthWidget
, specifically:
CompactMonthTimetable(
monthBuilder: (context, month) => Material(
color: Colors.white,
child: MonthWidget(
month,
dateBuilder: (context, date) {
assert(date.isValidTimetableDate);
return DateIndicator(
date,
style: DateIndicatorStyle(
context,
date,
textStyle: TextStyle(
color: selectedDate == date
? Colors.white
: Colors.black,
),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: selectedDate == date
? AppColors.primaryColor
: Colors.transparent,
),
),
);
},
weekBuilder: (context, week) => SizedBox.shrink(),
),
),
),
the issue is that now I don't know how to set dates from other months as disabled (different color)?
You can check whether date.firstDayOfMonth == month
and set the text style based on that
You can check whether
date.firstDayOfMonth == month
and set the text style based on that
Thanks for reply I will check it tomorrow morning and reply back here
style: DateIndicatorStyle(
context,
date,
textStyle: TextStyle(
color: selectedDate == date
? Colors.white
: date.firstDayOfMonth == month ? Colors.black : Colors.grey[500],
),
Worked! Thank you @JonasWanke