Permalink
Browse files

Fix ScrollView's snap index when scrolling forward and user taps the …

…screen again while still scrolling

Summary:
Currently when snapping is used with ScrollView it calculates wrong snap index if user taps the screen second time while ScrollView is still scrolling. This happens because the code only adds 1 to the snap index when translationAlongAxis is smaller than zero. When user taps screen second time the translationAlongAxis is 0 and snap index ends up being one less than it should. This causes the ScrollView to scroll one step backwards.

Bug can be reproduced with the new examples I added to UIExplorer's ScrollView in [scrollview-snap-bug-example branch](https://github.com/anttimo/react-native/tree/scrollview-snap-bug-example).

Fix can be verified by running the same examples with the ScrollView fix in [scrollview-snap-bug-example-with-fix branch](https://github.com/anttimo/react-native/tree/scrollview-snap-bug-example-with-fix).

![scrollview-bug](https://cloud.githubusercontent.com/assets/150881/14427555/10d59d1e-fffe-11
Closes #6906

Differential Revision: D3927123

Pulled By: majak

fbshipit-source-id: 38828cc60a02a754bdc3ec72fb98d8777917f15e
  • Loading branch information...
1 parent 0ce2bbd commit 72e203bf9572f2dbd6e836f35db3afdfdba3d6c4 @anttimo anttimo committed with Facebook Github Bot 7 Sep 26, 2016
Showing with 12 additions and 1 deletion.
  1. +12 −1 React/Views/RCTScrollView.m
@@ -381,6 +381,10 @@ @implementation RCTScrollView
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 @@ - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoi
// 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

0 comments on commit 72e203b

Please sign in to comment.