From f92279484f7e5249dd2e2fac02fa5fd727a48f02 Mon Sep 17 00:00:00 2001 From: Shin Yamamoto Date: Sat, 21 Jan 2023 09:15:23 +0900 Subject: [PATCH] Fix the buggy scroll tracking This commit sets the initial scroll offset to the pinning offset. The previous implementation, which set it to the current content offset, leads various scroll tracking bugs. This reproduction is one of issues. Using 'Scroll tracking(UITableView)' in Samples app. 1. Bounce the scroll content at the top most anchor. 2. Pull down the panel in bouncing at a minus content offset. (the scroll content stops at the minus offset.) 3. Pull up it The previous implementation was implemented for #526/#527. But now the issue hasn't been reproduced in v2.5.6. --- Sources/Core.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Sources/Core.swift b/Sources/Core.swift index a452221f..2e1efd1c 100644 --- a/Sources/Core.swift +++ b/Sources/Core.swift @@ -802,16 +802,21 @@ class Core: NSObject, UIGestureRecognizerDelegate { if surfaceView.grabberAreaContains(location) { initialScrollOffset = scrollView.contentOffset } else { - initialScrollOffset = scrollView.contentOffset - let offsetDiff = scrollView.contentOffset - contentOffsetForPinning(of: scrollView) + let pinningOffset = contentOffsetForPinning(of: scrollView) + + // `scrollView.contentOffset` can be a value in [-30, 0) at this time by `allowScrollPanGesture(for:)`. + // Therefore the initial scroll offset must be reset to the pinning offset. Otherwise, the following + // `Fit the surface bounds` logic don't working and also the scroll content offset can be invalid. + initialScrollOffset = pinningOffset + + // Fit the surface bounds to a scroll offset content by startInteraction(at:offset:) + let offsetDiff = scrollView.contentOffset - pinningOffset switch layoutAdapter.position { case .top, .left: - // Fit the surface bounds to a scroll offset content by startInteraction(at:offset:) if value(of: offsetDiff) > 0 { offset = -offsetDiff } case .bottom, .right: - // Fit the surface bounds to a scroll offset content by startInteraction(at:offset:) if value(of: offsetDiff) < 0 { offset = -offsetDiff }