Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect behavior when firstDay parameter changes #842

Open
kenfoo opened this issue Dec 24, 2023 · 3 comments
Open

Incorrect behavior when firstDay parameter changes #842

kenfoo opened this issue Dec 24, 2023 · 3 comments
Labels
bug Something isn't working

Comments

@kenfoo
Copy link

kenfoo commented Dec 24, 2023

If firstDay parameter is changed with a state change, the displayed calendar changes to something that is incorrect and behavior becomes erratic.

A simple code which starts with

int firstYear=2023

And in the build method of the widget:

      // Set today's date to 24th Dec 2023
      final now = DateTime.utc(2023, 12, 24);
      return Column(
        children: [
          Expanded(
            flex: 1,
            child: TableCalendar(
              shouldFillViewport: true,
              firstDay: DateTime.utc(firstYear, 1, 1),
              lastDay: DateTime.utc(now.year, 12, 31),
              focusedDay: now,
              calendarBuilders: CalendarBuilders(
                outsideBuilder: (context, day, focusedDay) => Container(),
              ),
            ),
          ),
          FilledButton(
              onPressed: () {
                setState(() => firstYear = 1985);
              },
              child: const Text('Change first year'))
        ],
      );

On first render, calendar works properly. The correct days are shown and if you tap the right button to move to the next month, the calendar doesn't allow you to, since lastDay is 31st Dec 2023.

Once we hit the "Change first year" button which changes the firstDay to 1st Jan 1985, the run of dates in the calendar changes to something that doesn't make sense. And if you tap the right button, the month & year still remains as December 2023, but the run of days shows only 29th, 30th, 31st, which doesn't make sense.

@kenfoo kenfoo added the bug Something isn't working label Dec 24, 2023
@niemsie
Copy link

niemsie commented Jan 9, 2024

@kenfoo I had a similar problem. It seems like the calendar does not like having its parameters that affect the first/last day and focused day changed during a rebuild.

I fixed it by providing a static key to the calendar, meaning Flutter should reuse the same instance of the calendar on a rebuild from setState and only provide the updated parameters:

  static final _uniqueCalendarKey = UniqueKey();

  /// Then inside `build`:
  TableCalendar(
              key: _uniqueCalendarKey
              ...
  )

Let me know if this helps you, if you see any concerns with this, or if any side effects arise.

@yhlbr
Copy link

yhlbr commented Apr 15, 2024

@niemsie your solution didn't work for me, but it got me into the right direction.
To force a full reset of the calendar widget, I changed the key when changing the first or last day.

My Code looks like the following:

class LessonsCalendar extends StatefulWidget {
  final DateTime startDate;
  final DateTime endDate;

  LessonsCalendar(
      {required this.startDate, required this.endDate});

  @override
  _LessonsCalendarState createState() => _LessonsCalendarState();
}

class _LessonsCalendarState extends State<LessonsCalendar> {

  static var _calendarKeyCount = 0;

  @mustCallSuper
  @protected
  void didUpdateWidget(oldWidget) {
    super.didUpdateWidget(oldWidget);
    setState(() {
      _selectedDay = _focusedDay = DateTime.now();
      ...
      _calendarKeyCount += 1;
    });
  }


  @override
  Widget build(BuildContext context) {
     ...
     KeyedSubtree(
          key: ValueKey<int>(_calendarKeyCount),
          child: TableCalendar(
            // Configuration
            firstDay: widget.startDate,
            lastDay: widget.endDate,
     ...

Hopefully this works for you too @kenfoo

I'm not sure if there is a better way of doing this, at least it works for now.
I got the solution from here: https://stackoverflow.com/a/64183322/13319613

@Somtobro
Copy link

Bro, totally random but, any idea on how to implement day to day swiping?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants