Improve swipable row gestures to feel more natural

Summary: Modified logic and constants to make the swipable row animations feel more natural and smooth.

Reviewed By: fred2028

Differential Revision: D3801391

fbshipit-source-id: d4301fe01a190803b5bc27373a9755086b6c431d
This commit is contained in:
Kaitlyn Lee 2016-08-31 18:07:14 -07:00 committed by Facebook Github Bot 5
parent 46b54fd7a8
commit 1e5d52bf0b
1 changed files with 26 additions and 4 deletions

View File

@ -48,7 +48,7 @@ const HORIZONTAL_FULL_SWIPE_SPEED_THRESHOLD = 0.3;
// Factor to divide by to get slow speed; i.e. 4 means 1/4 of full speed // Factor to divide by to get slow speed; i.e. 4 means 1/4 of full speed
const SLOW_SPEED_SWIPE_FACTOR = 4; const SLOW_SPEED_SWIPE_FACTOR = 4;
// Time, in milliseconds, of how long the animated swipe should be // Time, in milliseconds, of how long the animated swipe should be
const SWIPE_DURATION = 200; const SWIPE_DURATION = 300;
/** /**
* On SwipeableListView mount, the 1st item will bounce to show users it's * On SwipeableListView mount, the 1st item will bounce to show users it's
@ -58,8 +58,8 @@ const ON_MOUNT_BOUNCE_DELAY = 700;
const ON_MOUNT_BOUNCE_DURATION = 400; const ON_MOUNT_BOUNCE_DURATION = 400;
// Distance left of closed position to bounce back when right-swiping from closed // Distance left of closed position to bounce back when right-swiping from closed
const RIGHT_SWIPE_BOUNCE_BACK_DISTANCE = 50; const RIGHT_SWIPE_BOUNCE_BACK_DISTANCE = 30;
const RIGHT_SWIPE_BOUNCE_BACK_DURATION = 400; const RIGHT_SWIPE_BOUNCE_BACK_DURATION = 300;
/** /**
* Max distance of right swipe to allow (right swipes do functionally nothing). * Max distance of right swipe to allow (right swipes do functionally nothing).
* Must be multiplied by SLOW_SPEED_SWIPE_FACTOR because gestureState.dx tracks * Must be multiplied by SLOW_SPEED_SWIPE_FACTOR because gestureState.dx tracks
@ -295,6 +295,28 @@ const SwipeableRow = React.createClass({
this._animateTo(-maxSwipeDistance); this._animateTo(-maxSwipeDistance);
}, },
_animateToOpenPositionWith(
speed: number,
distMoved: number,
): void {
/**
* Ensure the speed is at least the set speed threshold to prevent a slow
* swiping animation
*/
speed = (
speed > HORIZONTAL_FULL_SWIPE_SPEED_THRESHOLD ?
speed :
HORIZONTAL_FULL_SWIPE_SPEED_THRESHOLD
);
/**
* Calculate the duration the row should take to swipe the remaining distance
* at the same speed the user swiped (or the speed threshold)
*/
const duration = Math.abs((this.props.maxSwipeDistance - Math.abs(distMoved)) / speed);
const maxSwipeDistance = IS_RTL ? -this.props.maxSwipeDistance : this.props.maxSwipeDistance;
this._animateTo(-maxSwipeDistance, duration);
},
_animateToClosedPosition(duration: number = SWIPE_DURATION): void { _animateToClosedPosition(duration: number = SWIPE_DURATION): void {
this._animateTo(CLOSED_LEFT_POSITION, duration); this._animateTo(CLOSED_LEFT_POSITION, duration);
}, },
@ -343,7 +365,7 @@ const SwipeableRow = React.createClass({
if (horizontalDistance < 0) { if (horizontalDistance < 0) {
// Swiped left // Swiped left
this.props.onOpen(); this.props.onOpen();
this._animateToOpenPosition(); this._animateToOpenPositionWith(gestureState.vx, horizontalDistance);
} else { } else {
// Swiped right // Swiped right
this._animateToClosedPosition(); this._animateToClosedPosition();