Skip to content

Commit

Permalink
Bring back the previous snap helper
Browse files Browse the repository at this point in the history
  • Loading branch information
kizitonwose committed Dec 13, 2023
1 parent f58f53b commit 4955820
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 7 deletions.
30 changes: 26 additions & 4 deletions view/src/main/java/com/kizitonwose/calendar/view/CalendarView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import androidx.core.content.withStyledAttributes
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import com.kizitonwose.calendar.core.CalendarDay
import com.kizitonwose.calendar.core.CalendarMonth
import com.kizitonwose.calendar.core.DayPosition
import com.kizitonwose.calendar.core.OutDateStyle
import com.kizitonwose.calendar.data.checkDateRange
import com.kizitonwose.calendar.view.internal.CalendarPageSnapHelper
import com.kizitonwose.calendar.view.internal.CalendarPageSnapHelperLegacy
import com.kizitonwose.calendar.view.internal.monthcalendar.MonthCalendarAdapter
import com.kizitonwose.calendar.view.internal.monthcalendar.MonthCalendarLayoutManager
import java.time.DayOfWeek
Expand Down Expand Up @@ -117,6 +119,7 @@ open class CalendarView : RecyclerView {
if (field != value) {
field = value
(layoutManager as? MonthCalendarLayoutManager)?.orientation = value
updateSnapHelper()
}
}

Expand All @@ -129,7 +132,7 @@ open class CalendarView : RecyclerView {
set(value) {
if (field != value) {
field = value
pagerSnapHelper.attachToRecyclerView(if (scrollPaged) this else null)
updateSnapHelper()
}
}

Expand Down Expand Up @@ -180,7 +183,9 @@ open class CalendarView : RecyclerView {
}
}

private val pagerSnapHelper = CalendarPageSnapHelper()
private val horizontalSnapHelper = CalendarPageSnapHelperLegacy()
private val verticalSnapHelper = CalendarPageSnapHelper()
private var pageSnapHelper: PagerSnapHelper = horizontalSnapHelper

private var startMonth: YearMonth? = null
private var endMonth: YearMonth? = null
Expand Down Expand Up @@ -225,10 +230,10 @@ open class CalendarView : RecyclerView {
R.styleable.CalendarView_cv_scrollPaged,
orientation == HORIZONTAL,
)
daySize = DaySize.values()[
daySize = DaySize.entries[
getInt(R.styleable.CalendarView_cv_daySize, daySize.ordinal),
]
outDateStyle = OutDateStyle.values()[
outDateStyle = OutDateStyle.entries[
getInt(R.styleable.CalendarView_cv_outDateStyle, outDateStyle.ordinal),
]
monthViewClass = getString(R.styleable.CalendarView_cv_monthViewClass)
Expand Down Expand Up @@ -256,6 +261,23 @@ open class CalendarView : RecyclerView {
post { calendarAdapter.notifyMonthScrollListenerIfNeeded() }
}

private fun updateSnapHelper() {
if (!scrollPaged) {
pageSnapHelper.attachToRecyclerView(null)
return
}
if (
(orientation == HORIZONTAL && pageSnapHelper !== horizontalSnapHelper) ||
(orientation != VERTICAL && pageSnapHelper !== verticalSnapHelper)
) {
// Remove the currently attached snap helper.
pageSnapHelper.attachToRecyclerView(null)
pageSnapHelper =
if (orientation == HORIZONTAL) horizontalSnapHelper else verticalSnapHelper
}
pageSnapHelper.attachToRecyclerView(this)
}

/**
* Scroll to a specific month on the calendar. This instantly
* shows the view for the month without any animations.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.kizitonwose.calendar.core.Week
import com.kizitonwose.calendar.core.WeekDay
import com.kizitonwose.calendar.data.checkDateRange
import com.kizitonwose.calendar.view.internal.CalendarPageSnapHelper
import com.kizitonwose.calendar.view.internal.CalendarPageSnapHelperLegacy
import com.kizitonwose.calendar.view.internal.weekcalendar.WeekCalendarAdapter
import com.kizitonwose.calendar.view.internal.weekcalendar.WeekCalendarLayoutManager
import java.time.DayOfWeek
Expand Down Expand Up @@ -150,7 +150,7 @@ open class WeekCalendarView : RecyclerView {
}
}

private val pagerSnapHelper = CalendarPageSnapHelper()
private val pagerSnapHelper = CalendarPageSnapHelperLegacy()

private var startDate: LocalDate? = null
private var endDate: LocalDate? = null
Expand Down Expand Up @@ -190,7 +190,7 @@ open class WeekCalendarView : RecyclerView {
weekFooterResource,
)
scrollPaged = getBoolean(R.styleable.WeekCalendarView_cv_scrollPaged, scrollPaged)
daySize = DaySize.values()[
daySize = DaySize.entries[
getInt(R.styleable.WeekCalendarView_cv_daySize, daySize.ordinal),
]
weekViewClass = getString(R.styleable.WeekCalendarView_cv_weekViewClass)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.kizitonwose.calendar.view.internal

import android.view.View
import androidx.recyclerview.widget.OrientationHelper
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView

internal class CalendarPageSnapHelperLegacy : PagerSnapHelper() {

/**
* The default implementation of this method in [PagerSnapHelper.calculateDistanceToFinalSnap] uses the distance
* between the target view center vs RecyclerView center as final snap distance. This does not always give the
* desired result for calendar usage. For example in a vertical calendar when the RecyclerView is taller than
* the item view(e.g two or more visible months), we don't actually want the item view's center to be at the
* center of the RecyclerView when it snaps but instead we want the item view and RecyclerView top(in vertical)
* or left(in horizontal) to match at the end of the snap.
*
* Keeping this class to be used in horizontal calendar due to
* https://github.com/kizitonwose/Calendar/issues/466#issuecomment-1719337527
*/
override fun calculateDistanceToFinalSnap(
layoutManager: RecyclerView.LayoutManager,
targetView: View,
): IntArray {
return IntArray(2).apply {
this[0] = if (layoutManager.canScrollHorizontally()) {
distanceToStart(targetView, getHorizontalHelper(layoutManager))
} else 0

this[1] = if (layoutManager.canScrollVertically()) {
distanceToStart(targetView, getVerticalHelper(layoutManager))
} else 0
}
}

private fun distanceToStart(targetView: View, helper: OrientationHelper): Int {
val childStart = (helper.getDecoratedStart(targetView))
val containerStart = helper.startAfterPadding
return childStart - containerStart
}

private lateinit var verticalHelper: OrientationHelper
private lateinit var horizontalHelper: OrientationHelper

private fun getVerticalHelper(layoutManager: RecyclerView.LayoutManager): OrientationHelper {
if (!::verticalHelper.isInitialized || verticalHelper.layoutManager != layoutManager) {
verticalHelper = OrientationHelper.createVerticalHelper(layoutManager)
}
return verticalHelper
}

private fun getHorizontalHelper(layoutManager: RecyclerView.LayoutManager): OrientationHelper {
if (!::horizontalHelper.isInitialized || horizontalHelper.layoutManager != layoutManager) {
horizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager)
}
return horizontalHelper
}
}

0 comments on commit 4955820

Please sign in to comment.