From f8919108ec68cc77daffbcd3e13842c2567d6288 Mon Sep 17 00:00:00 2001 From: Kizito Nwose Date: Sat, 10 Aug 2019 11:47:13 +0100 Subject: [PATCH 1/2] Retain currently visible month if `setup()` is called multiple times. --- .../kizitonwose/calendarview/CalendarView.kt | 29 +++++++++++++++++-- .../calendarview/ui/CalendarLayoutManager.kt | 8 ++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/library/src/main/java/com/kizitonwose/calendarview/CalendarView.kt b/library/src/main/java/com/kizitonwose/calendarview/CalendarView.kt index 691403d0..82db2d99 100644 --- a/library/src/main/java/com/kizitonwose/calendarview/CalendarView.kt +++ b/library/src/main/java/com/kizitonwose/calendarview/CalendarView.kt @@ -9,6 +9,7 @@ import androidx.recyclerview.widget.PagerSnapHelper import androidx.recyclerview.widget.RecyclerView import com.kizitonwose.calendarview.model.* import com.kizitonwose.calendarview.ui.* +import com.kizitonwose.calendarview.utils.NO_INDEX import org.threeten.bp.DayOfWeek import org.threeten.bp.LocalDate import org.threeten.bp.YearMonth @@ -402,8 +403,14 @@ open class CalendarView : RecyclerView { post { calendarAdapter.notifyMonthScrollListenerIfNeeded() } } - private fun updateAdapterMonthConfig() { + private fun updateAdapterMonthConfig(saveScroll: Boolean = false) { if (adapter != null) { + val visiblePosition = calendarLayoutManager.findFirstVisibleItemPosition() + val visibleView = calendarLayoutManager.findViewByPosition(visiblePosition) + + val viewOffset = (if (isVertical) visibleView?.top else visibleView?.left) ?: 0 + val visibleMonth = calendarAdapter.monthConfig.months[visiblePosition] + calendarAdapter.monthConfig = MonthConfig( outDateStyle, inDateStyle, maxRowCount, @@ -411,7 +418,17 @@ open class CalendarView : RecyclerView { hasBoundaries ) calendarAdapter.notifyDataSetChanged() - post { calendarAdapter.notifyMonthScrollListenerIfNeeded() } + + post { + if (saveScroll) { // Scroll to the previously visible month with offset. + val visibleMonthNewPos = calendarAdapter.monthConfig.months.indexOf(visibleMonth) + if (visibleMonthNewPos != NO_INDEX) { + calendarLayoutManager.scrollToPositionWithOffset(visibleMonthNewPos, viewOffset) + } + } + calendarAdapter.notifyMonthScrollListenerIfNeeded() + } + } } @@ -569,6 +586,14 @@ open class CalendarView : RecyclerView { * @param firstDayOfWeek An instance of [DayOfWeek] enum to be the first day of week. */ fun setup(startMonth: YearMonth, endMonth: YearMonth, firstDayOfWeek: DayOfWeek) { + if (this.startMonth != null && this.endMonth != null && this.firstDayOfWeek != null) { + this.startMonth = startMonth + this.endMonth = endMonth + this.firstDayOfWeek = firstDayOfWeek + updateAdapterMonthConfig(saveScroll = true) + return // Only update the months on the calendar, no need for a full setup. + } + this.startMonth = startMonth this.endMonth = endMonth this.firstDayOfWeek = firstDayOfWeek diff --git a/library/src/main/java/com/kizitonwose/calendarview/ui/CalendarLayoutManager.kt b/library/src/main/java/com/kizitonwose/calendarview/ui/CalendarLayoutManager.kt index bf283c5e..f4dc9d6d 100644 --- a/library/src/main/java/com/kizitonwose/calendarview/ui/CalendarLayoutManager.kt +++ b/library/src/main/java/com/kizitonwose/calendarview/ui/CalendarLayoutManager.kt @@ -50,14 +50,14 @@ internal class CalendarLayoutManager(private val calView: CalendarView, @Recycle if (monthPosition != NO_INDEX) { val viewHolder = calView.findViewHolderForAdapterPosition(monthPosition) as? MonthViewHolder ?: return@post - val offset = calculateOffset(day, viewHolder.itemView) + val offset = calculateDayViewOffsetInParent(day, viewHolder.itemView) scrollToPositionWithOffset(monthPosition, -offset) calView.post { adapter.notifyMonthScrollListenerIfNeeded() } } } } - private fun calculateOffset(day: CalendarDay, itemView: View): Int { + private fun calculateDayViewOffsetInParent(day: CalendarDay, itemView: View): Int { val dayView = itemView.findViewById(day.date.hashCode()) ?: return 0 val rect = Rect() dayView.getDrawingRect(rect) @@ -85,7 +85,7 @@ internal class CalendarLayoutManager(private val calView: CalendarView, @Recycle if (day == null) { return dy } - val offset = calculateOffset(day, view) + val offset = calculateDayViewOffsetInParent(day, view) return dy - offset } @@ -94,7 +94,7 @@ internal class CalendarLayoutManager(private val calView: CalendarView, @Recycle if (day == null) { return dx } - val offset = calculateOffset(day, view) + val offset = calculateDayViewOffsetInParent(day, view) return dx - offset } } From d9d1dceccf63f36e7fc176f3b29c29487954faa4 Mon Sep 17 00:00:00 2001 From: Kizito Nwose Date: Sat, 10 Aug 2019 12:09:42 +0100 Subject: [PATCH 2/2] Simplify setup method. --- .../com/kizitonwose/calendarview/CalendarView.kt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/library/src/main/java/com/kizitonwose/calendarview/CalendarView.kt b/library/src/main/java/com/kizitonwose/calendarview/CalendarView.kt index 82db2d99..9b35352f 100644 --- a/library/src/main/java/com/kizitonwose/calendarview/CalendarView.kt +++ b/library/src/main/java/com/kizitonwose/calendarview/CalendarView.kt @@ -586,18 +586,19 @@ open class CalendarView : RecyclerView { * @param firstDayOfWeek An instance of [DayOfWeek] enum to be the first day of week. */ fun setup(startMonth: YearMonth, endMonth: YearMonth, firstDayOfWeek: DayOfWeek) { - if (this.startMonth != null && this.endMonth != null && this.firstDayOfWeek != null) { - this.startMonth = startMonth - this.endMonth = endMonth - this.firstDayOfWeek = firstDayOfWeek - updateAdapterMonthConfig(saveScroll = true) - return // Only update the months on the calendar, no need for a full setup. - } + val oldStartMonth = this.startMonth + val oldEndMonth = this.endMonth + val oldFirstDayOfWeek = this.firstDayOfWeek this.startMonth = startMonth this.endMonth = endMonth this.firstDayOfWeek = firstDayOfWeek + if (oldStartMonth != null && oldEndMonth != null && oldFirstDayOfWeek != null) { + updateAdapterMonthConfig(saveScroll = true) + return // Only update the months on the calendar, no need for a full setup. + } + clipToPadding = false clipChildren = false //#ClipChildrenFix