From 1cefb278437b41e9c6cdf21537aa65b7ae061f76 Mon Sep 17 00:00:00 2001 From: "satyajit.happy" Date: Wed, 19 Jun 2019 09:37:08 +0200 Subject: [PATCH] fix: don't consider velocity and gesture distance if gesture didn't end previously, when gesture wasn't active, we checked if the gesture exceeded the minimum threshold (this was due to activeOffsetX not being respected on Android), - if yes, we calculate the next position based on gesture distance or velocity - if no, we transition to what the value of index was this addressed 2 cases: the first condition would trigger when a gesture was performed, the second one will trigger if the index changed due to other means such as state update. this check was mistakenly removed in https://github.com/react-native-community/react-native-tab-view/commit/e7f832c the new code checked for `State.END`, which resulted in the tab switch due to state update not working at times. this is because the `gestureState` value is different when a gesture was cancelled, e.g. due to a vertical gesture or focus on an input element. closes #806, closes #809 --- package.json | 2 +- src/Pager.tsx | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 95051c29..23a8fe41 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "lint": "eslint --ext .js,.ts,.tsx .", "release": "release-it", "example": "yarn --cwd example", - "bootstrap": "yarn && yarn example", + "bootstrap": "yarn example && yarn", "prepare": "bob build" }, "publishConfig": { diff --git a/src/Pager.tsx b/src/Pager.tsx index ad58eca4..7b1aeb6a 100644 --- a/src/Pager.tsx +++ b/src/Pager.tsx @@ -42,6 +42,7 @@ const { Clock, Value, onChange, + and, abs, add, block, @@ -188,7 +189,7 @@ export default class Pager extends React.Component> { // Current state of the gesture private velocityX = new Value(0); private gestureX = new Value(0); - private gestureState = new Value(State.END); + private gestureState = new Value(State.UNDETERMINED); private offsetX = new Value(0); // Current progress of the page (translateX value) @@ -415,6 +416,7 @@ export default class Pager extends React.Component> { divide(abs(this.velocityX), this.velocityX), 0 ); + private extrapolatedPosition = add( this.gestureX, multiply( @@ -514,14 +516,20 @@ export default class Pager extends React.Component> { // Stop animations while we're dragging stopClock(this.clock), ], - - cond(eq(this.gestureState, State.END), [ + [ set(this.isSwiping, FALSE), this.transitionTo( cond( - greaterThan( - abs(this.extrapolatedPosition), - divide(this.layoutWidth, 2) + and( + // We should consider velocity and gesture distance only when a swipe ends + // The gestureX value will be non-zero when swipe has happened + // We check against a minimum distance instead of 0 because `activeOffsetX` doesn't seem to be respected on Android + // For other factors such as state update, the velocity and gesture distance don't matter + greaterThan(abs(this.gestureX), SWIPE_DISTANCE_MINIMUM), + greaterThan( + abs(this.extrapolatedPosition), + divide(this.layoutWidth, 2) + ) ), // For swipe gesture, to calculate the index, determine direction and add to index // When the user swipes towards the left, we transition to the next tab @@ -546,7 +554,7 @@ export default class Pager extends React.Component> { this.index ) ), - ]) + ] ), this.progress, ]);