@@ -71,10 +71,14 @@ class RecordsCalendarView @JvmOverloads constructor(
7171 // End of attrs
7272
7373 private var isScaling: Boolean = false
74+ private var isSwiping: Boolean = false
7475 private var scaleFactor: Float = 1f
7576 private var lastScaleFactor: Float = 1f
7677 private var panFactor: Float = 0f
7778 private var lastPanFactor: Float = 0f
79+ private var swipeStartOffset: Float = 0f
80+ private var swipeStartPanFactor: Float = 0f
81+ private var shouldRebaseSwipeAfterScaleStop: Boolean = false
7882 private var legendTextWidth: Float = 0f
7983 private var legendTextHeight: Float = 0f
8084 private var legendTopTextHeight: Float = 0f
@@ -175,6 +179,7 @@ class RecordsCalendarView @JvmOverloads constructor(
175179 )
176180 private val swipeDetector = SwipeDetector (
177181 context = context,
182+ onSlideStart = ::onEventSwipeStart,
178183 onSlide = ::onEventSwipe,
179184 onSlideStop = ::onEventSwipeStop,
180185 )
@@ -931,6 +936,7 @@ class RecordsCalendarView @JvmOverloads constructor(
931936
932937 private fun onEventScaleStart () {
933938 isScaling = true
939+ if (isSwiping) lastPanFactor = panFactor
934940 }
935941
936942 private fun onEventScaleChanged (newScale : Float ) {
@@ -944,10 +950,18 @@ class RecordsCalendarView @JvmOverloads constructor(
944950 }
945951
946952 private fun onEventScaleStop () {
947- parent.requestDisallowInterceptTouchEvent(false )
953+ parent.requestDisallowInterceptTouchEvent(isSwiping )
948954 lastScaleFactor = scaleFactor
949955 lastPanFactor = panFactor
950956 isScaling = false
957+ shouldRebaseSwipeAfterScaleStop = isSwiping
958+ }
959+
960+ private fun onEventSwipeStart () {
961+ isSwiping = true
962+ shouldRebaseSwipeAfterScaleStop = false
963+ swipeStartOffset = 0f
964+ swipeStartPanFactor = panFactor
951965 }
952966
953967 @Suppress(" UNUSED_PARAMETER" )
@@ -956,15 +970,23 @@ class RecordsCalendarView @JvmOverloads constructor(
956970 direction : SwipeDetector .Direction ,
957971 event : MotionEvent ,
958972 ) {
959- if (! direction.isHorizontal() && ! isScaling) {
960- parent.requestDisallowInterceptTouchEvent(true )
961- panFactor = lastPanFactor + offset
962- coercePan()
963- invalidate()
973+ if (direction.isHorizontal() || isScaling) return
974+ // Keep swipe baseline in sync with active pinch to avoid handoff jumps.
975+ if (shouldRebaseSwipeAfterScaleStop) {
976+ shouldRebaseSwipeAfterScaleStop = false
977+ swipeStartOffset = offset
978+ swipeStartPanFactor = panFactor
979+ return
964980 }
981+ parent.requestDisallowInterceptTouchEvent(true )
982+ panFactor = swipeStartPanFactor + (offset - swipeStartOffset)
983+ coercePan()
984+ invalidate()
965985 }
966986
967987 private fun onEventSwipeStop () {
988+ isSwiping = false
989+ shouldRebaseSwipeAfterScaleStop = false
968990 if (isScaling) return
969991 parent.requestDisallowInterceptTouchEvent(false )
970992 lastPanFactor = panFactor
0 commit comments