Permalink
Browse files

Improve feel of scroll snapping behavior on iOS

Reviewed By: sahrens, shergin

Differential Revision: D4768384

fbshipit-source-id: 6319d058292be6ba38c059d8d1a1bf70bac603e2
  • Loading branch information...
sophiebits authored and facebook-github-bot committed Mar 29, 2017
1 parent c233191 commit 1d367004e903c3a4695386d067edda1203132523
Showing with 11 additions and 20 deletions.
  1. +11 −20 React/Views/RCTScrollView.m
@@ -326,10 +326,6 @@ @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
@@ -667,32 +663,27 @@ - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoi
BOOL isHorizontal = [self isHorizontal:scrollView];
// What is the current offset?
CGFloat velocityAlongAxis = isHorizontal ? velocity.x : velocity.y;
CGFloat targetContentOffsetAlongAxis = isHorizontal ? targetContentOffset->x : targetContentOffset->y;
// Which direction is the scroll travelling?
CGPoint translation = [scrollView.panGestureRecognizer translationInView:scrollView];
CGFloat translationAlongAxis = isHorizontal ? translation.x : translation.y;
// Offset based on desired alignment
CGFloat frameLength = isHorizontal ? self.frame.size.width : self.frame.size.height;
CGFloat alignmentOffset = 0.0f;
if ([self.snapToAlignment isEqualToString: @"center"]) {
if ([self.snapToAlignment isEqualToString: @"center"]) {
alignmentOffset = (frameLength * 0.5f) + (snapToIntervalF * 0.5f);
} else if ([self.snapToAlignment isEqualToString: @"end"]) {
} else if ([self.snapToAlignment isEqualToString: @"end"]) {
alignmentOffset = frameLength;
}
// Pick snap point based on direction and proximity
NSInteger snapIndex = floor((targetContentOffsetAlongAxis + alignmentOffset) / snapToIntervalF);
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;
CGFloat fractionalIndex = (targetContentOffsetAlongAxis + alignmentOffset) / snapToIntervalF;
NSInteger snapIndex =
velocityAlongAxis > 0.0 ?
ceil(fractionalIndex) :
velocityAlongAxis < 0.0 ?
floor(fractionalIndex) :
round(fractionalIndex);
CGFloat newTargetContentOffset = (snapIndex * snapToIntervalF) - alignmentOffset;
// Set new targetContentOffset
if (isHorizontal) {

0 comments on commit 1d36700

Please sign in to comment.