material-calendarview icon indicating copy to clipboard operation
material-calendarview copied to clipboard

Date in Title always starts with today

Open fabianbouchal opened this issue 5 years ago • 4 comments

Picture the following scenario

  • I have a range of enabled days e.g. March 1st until March 15th of the year 2020 displayed in month mode
  • When I display the calendar view, the enabled day range is displayed and the other days of march are greyed out, as I specified.
  • The problem is, the top header title of the view always shows the month of the today, so if I display the view in June 2020, the title will read "June 2020" instead of "March 2020".

Am I missing something here? In my opinion the header title should always be the month and year of the dates displayed below by default. It doesn't make sense to use todays month and year if a different month is displayed below.

Does anyone have an idea how I can change that or how I can override the title based on the month that is displayed in the calendar view? Any input is highly appreciated.

fabianbouchal avatar Apr 09 '20 19:04 fabianbouchal

would you please elaborate more clear

devrajmaker avatar Jul 11 '20 07:07 devrajmaker

would you please elaborate more clear

Would you please elaborate what's unclear

fabianbouchal avatar Jul 11 '20 14:07 fabianbouchal

I've done some digging on this and can somewhat point you to the cause.

The title is updated based on currentMonth. The only thing that primarily updates currentMonth is the onPageSelected listener method that is listening to page changes from the pageAdapter which only gets called when the currentItem for the page adapter changes.

The problem is that there are things that you can do that changes the interpretation of how an index maps to a date that do not trigger the onPageSelected to be called. This primarily concerns changes in the min/max dates.

So here is a scenario that will demonstrate the problem:

  • Show the month calendar with currentDate of today and min/max for the start and end of the current month
  • Change the min/max to the start and end of some month in the past
  • You will see that the title shows the current month, but the calendar itself is the correct month

The reason for this behavior is that those changes do not result in a call to onPageSelected, because the pager index in both cases is 0.

If you look at setRangeDates method, it handles the case where currentMonth is before the new minimum and moves currentMonth forward, but it does not handle the case where currentMonth is after the new maximum. The call to adapter.getIndexForDay(c) will move the pager to the correct month, but it does not update currentMonth and in the scenario I laid out the index in the pager does not change (it will be zero) so the onPageListener will not get called either to update the currentMonth since the index did not change.

I think this might be a better implementation of setRangeDates that would fix the problem:

  private void setRangeDates(CalendarDay min, CalendarDay max) {
    adapter.setRangeDates(min, max);
    int position = adapter.getIndexForDay(currentMonth);
    pager.setCurrentItem(position, false);
    pageChangeListener.onPageSelected(position);
  }

dalewking avatar Aug 02 '21 22:08 dalewking

I have implemented this hack in our Kotlin code that I call after committing the state with the modified min/max and it seems to work:

private val pageChangeListener: Field by lazy {
    MaterialCalendarView::class.java
        .getDeclaredField("pageChangeListener")
        .apply { isAccessible = true }
}

private val viewPager: Field by lazy {
    MaterialCalendarView::class.java
        .getDeclaredField("pager")
        .apply { isAccessible = true }
}

And this code called after setting date range

    // FIXME: This is work around for cases where the title is not getting updated by calendar view
    //        See https://github.com/prolificinteractive/material-calendarview/issues/1035
    (pageChangeListener.get(this) as ViewPager.OnPageChangeListener)
        .onPageSelected((viewPager.get(this) as ViewPager).currentItem)

dalewking avatar Aug 02 '21 23:08 dalewking