diff --git a/packages/stack/example/src/SimpleStack.js b/packages/stack/example/src/SimpleStack.js
index c6252be5..9142e712 100644
--- a/packages/stack/example/src/SimpleStack.js
+++ b/packages/stack/example/src/SimpleStack.js
@@ -63,10 +63,17 @@ class DetailsScreen extends React.Component {
}}
>
Details Screen
+
);
}
+
+ _goBackInTwoSeconds = () => {
+ setTimeout(() => {
+ this.props.navigation.goBack();
+ }, 2000);
+ };
}
class HeaderlessScreen extends React.Component {
diff --git a/packages/stack/src/views/StackView/StackView.js b/packages/stack/src/views/StackView/StackView.js
index 3521c2bd..15e95c1f 100644
--- a/packages/stack/src/views/StackView/StackView.js
+++ b/packages/stack/src/views/StackView/StackView.js
@@ -1,13 +1,11 @@
import React from 'react';
-import { NativeModules } from 'react-native';
import { StackActions } from '@react-navigation/core';
import StackViewLayout from './StackViewLayout';
import Transitioner from '../Transitioner';
import TransitionConfigs from './StackViewTransitionConfigs';
-const NativeAnimatedModule =
- NativeModules && NativeModules.NativeAnimatedModule;
+const USE_NATIVE_DRIVER = true;
// NOTE(brentvatne): this was previously in defaultProps, but that is deceiving
// because the entire object will be clobbered by navigationConfig that is
@@ -67,7 +65,7 @@ class StackView extends React.Component {
prevTransitionProps,
this.props.navigationConfig.mode === 'modal'
).transitionSpec,
- useNativeDriver: !!NativeAnimatedModule,
+ useNativeDriver: USE_NATIVE_DRIVER,
};
};
diff --git a/packages/stack/src/views/StackView/StackViewLayout.js b/packages/stack/src/views/StackView/StackViewLayout.js
index 4d74fb94..12ff492e 100644
--- a/packages/stack/src/views/StackView/StackViewLayout.js
+++ b/packages/stack/src/views/StackView/StackViewLayout.js
@@ -90,9 +90,6 @@ class StackViewLayout extends React.Component {
*/
_gestureStartValue = 0;
- // tracks if a touch is currently happening
- _isResponding = false;
-
/**
* immediateIndex is used to represent the expected index that we will be on after a
* transition. To achieve a smooth animation when swiping back, the action to go back
@@ -203,7 +200,7 @@ class StackViewLayout extends React.Component {
const onCompleteAnimation = () => {
this._immediateIndex = null;
const backFromScene = scenes.find(s => s.index === toValue + 1);
- if (!this._isResponding && backFromScene) {
+ if (backFromScene) {
navigation.dispatch(
NavigationActions.back({
key: backFromScene.route.key,
@@ -310,6 +307,14 @@ class StackViewLayout extends React.Component {
}
}
+ componentDidUpdate(prevProps) {
+ const { state: prevState } = prevProps.transitionProps.navigation;
+ const { state } = this.props.transitionProps.navigation;
+ if (prevState.index !== state.index) {
+ this._maybeCancelGesture();
+ }
+ }
+
_getGestureResponseDistance = () => {
const { scene } = this.props.transitionProps;
const { options } = scene.descriptor;
@@ -392,7 +397,7 @@ class StackViewLayout extends React.Component {
this.props.transitionProps.position.setValue(Math.max(0, value));
};
- _computeHorizontalGestureValue = nativeEvent => {
+ _computeHorizontalGestureValue = ({ translationX }) => {
let {
transitionProps: { navigation, layout },
} = this.props;
@@ -402,15 +407,13 @@ class StackViewLayout extends React.Component {
// TODO: remove this __getValue!
let distance = layout.width.__getValue();
- let translationX = this._isMotionInverted()
- ? -1 * nativeEvent.translationX
- : nativeEvent.translationX;
+ let x = this._isMotionInverted() ? -1 * translationX : translationX;
- let value = index - translationX / distance;
+ let value = index - x / distance;
return clamp(index - 1, value, index);
};
- _computeVerticalGestureValue = nativeEvent => {
+ _computeVerticalGestureValue = ({ translationY }) => {
let {
transitionProps: { navigation, layout },
} = this.props;
@@ -420,15 +423,19 @@ class StackViewLayout extends React.Component {
// TODO: remove this __getValue!
let distance = layout.height.__getValue();
- let translationY = this._isMotionInverted()
- ? -1 * nativeEvent.translationY
- : nativeEvent.translationY;
- let value = index - translationY / distance;
+ let y = this._isMotionInverted() ? -1 * translationY : translationY;
+ let value = index - y / distance;
return clamp(index - 1, value, index);
};
_handlePanGestureStateChange = ({ nativeEvent }) => {
if (nativeEvent.oldState === State.ACTIVE) {
+ // Gesture was cancelled! For example, some navigation state update
+ // arrived while the gesture was active that cancelled it out
+ if (!this.state.gesturePosition) {
+ return;
+ }
+
if (this._isMotionVertical()) {
this._handleReleaseVertical(nativeEvent);
} else {
@@ -443,6 +450,16 @@ class StackViewLayout extends React.Component {
}
};
+ // note: this will not animated so nicely because the position is unaware
+ // of the gesturePosition, so if we are in the middle of swiping the screen away
+ // and back is programatically fired then we will reset to the initial position
+ // and animate from there
+ _maybeCancelGesture = () => {
+ if (this.state.gesturePosition) {
+ this.setState({ gesturePosition: null });
+ }
+ };
+
_handleActivateGestureHorizontal = () => {
let { index } = this.props.transitionProps.navigation.state;
diff --git a/packages/stack/src/views/Transitioner.js b/packages/stack/src/views/Transitioner.js
index 3d26d8bf..0d3e7948 100644
--- a/packages/stack/src/views/Transitioner.js
+++ b/packages/stack/src/views/Transitioner.js
@@ -1,7 +1,6 @@
import React from 'react';
import { Animated, Easing, StyleSheet, View } from 'react-native';
import invariant from '../utils/invariant';
-import shallowEqual from '../utils/shallowEqual';
import NavigationScenesReducer from './ScenesReducer';
@@ -293,14 +292,6 @@ function isSceneActive(scene) {
return scene.isActive;
}
-function isRouteShallowEqual(a, b) {
- let routeA = { ...a };
- delete routeA.routes;
- let routeB = { ...b };
- delete routeB.routes;
- return shallowEqual(routeA, routeB);
-}
-
const styles = StyleSheet.create({
main: {
flex: 1,