diff --git a/React/Views/RCTScrollView.m b/React/Views/RCTScrollView.m index 1f0de2776..f36dc4eea 100644 --- a/React/Views/RCTScrollView.m +++ b/React/Views/RCTScrollView.m @@ -381,6 +381,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) uint16_t _coalescingKey; NSString *_lastEmittedEventName; NSHashTable *_scrollListeners; + // The last non-zero value of translationAlongAxis from scrollViewWillEndDragging. + // Tells if user was scrolling forward or backward and is used to determine a correct + // snap index when the user stops scrolling with a tap on the scroll view. + CGFloat _lastNonZeroTranslationAlongAxis; } - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher @@ -699,7 +703,14 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, onScroll) // Pick snap point based on direction and proximity NSInteger snapIndex = floor((targetContentOffsetAlongAxis + alignmentOffset) / snapToIntervalF); - snapIndex = (translationAlongAxis < 0) ? snapIndex + 1 : snapIndex; + BOOL isScrollingForward = translationAlongAxis < 0; + BOOL wasScrollingForward = translationAlongAxis == 0 && _lastNonZeroTranslationAlongAxis < 0; + if (isScrollingForward || wasScrollingForward) { + snapIndex = snapIndex + 1; + } + if (translationAlongAxis != 0) { + _lastNonZeroTranslationAlongAxis = translationAlongAxis; + } CGFloat newTargetContentOffset = ( snapIndex * snapToIntervalF ) - alignmentOffset; // Set new targetContentOffset