diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationAnimatedExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationAnimatedExample.js
index c27f3170d613b5..705f7d6be432eb 100644
--- a/Examples/UIExplorer/NavigationExperimental/NavigationAnimatedExample.js
+++ b/Examples/UIExplorer/NavigationExperimental/NavigationAnimatedExample.js
@@ -1,4 +1,11 @@
/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -13,20 +20,23 @@
*/
'use strict';
-var React = require('react-native');
-var {
+const React = require('react-native');
+
+const {
Animated,
NavigationExperimental,
StyleSheet,
ScrollView,
} = React;
-var NavigationExampleRow = require('./NavigationExampleRow');
-var {
+
+const NavigationExampleRow = require('./NavigationExampleRow');
+
+const {
AnimatedView: NavigationAnimatedView,
Card: NavigationCard,
- RootContainer: NavigationRootContainer,
- Reducer: NavigationReducer,
Header: NavigationHeader,
+ Reducer: NavigationReducer,
+ RootContainer: NavigationRootContainer,
} = NavigationExperimental;
const NavigationBasicReducer = NavigationReducer.StackReducer({
@@ -79,7 +89,7 @@ class NavigationAnimatedExample extends React.Component {
style={styles.animatedView}
renderOverlay={this._renderHeader}
applyAnimation={(pos, navState) => {
- Animated.timing(pos, {toValue: navState.index, duration: 1000}).start();
+ Animated.timing(pos, {toValue: navState.index, duration: 500}).start();
}}
renderScene={this._renderCard}
/>
diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationCardStackExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationCardStackExample.js
index b6aa01a7993937..2ac20280a70f8e 100644
--- a/Examples/UIExplorer/NavigationExperimental/NavigationCardStackExample.js
+++ b/Examples/UIExplorer/NavigationExperimental/NavigationCardStackExample.js
@@ -1,4 +1,11 @@
/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -14,7 +21,6 @@
'use strict';
const NavigationExampleRow = require('./NavigationExampleRow');
-const NavigationRootContainer = require('NavigationRootContainer');
const React = require('react-native');
const {
@@ -23,10 +29,13 @@ const {
ScrollView,
} = React;
-const NavigationCardStack = NavigationExperimental.CardStack;
-const NavigationStateUtils = NavigationExperimental.StateUtils;
+const {
+ CardStack: NavigationCardStack,
+ StateUtils: NavigationStateUtils,
+ RootContainer: NavigationRootContainer,
+} = NavigationExperimental;
-function reduceNavigationState(initialState) {
+function createReducer(initialState) {
return (currentState, action) => {
switch (action.type) {
case 'RootContainerInitialAction':
@@ -47,7 +56,7 @@ function reduceNavigationState(initialState) {
};
}
-const ExampleReducer = reduceNavigationState({
+const ExampleReducer = createReducer({
index: 0,
key: 'exmaple',
children: [{key: 'First Route'}],
diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js b/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js
index 258ce5bc8394bb..6e3d597f27c0e9 100644
--- a/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js
+++ b/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js
@@ -1,5 +1,10 @@
/**
- * Copyright (c) 2015, Facebook, Inc. All rights reserved.
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* Facebook, Inc. ("Facebook") owns all right, title and interest, including
* all intellectual property and other proprietary rights, in and to the React
@@ -28,36 +33,24 @@
'use strict';
const Animated = require('Animated');
+const NavigationCardStackStyleInterpolator = require('NavigationCardStackStyleInterpolator');
const NavigationContainer = require('NavigationContainer');
const NavigationLinearPanResponder = require('NavigationLinearPanResponder');
const NavigationPropTypes = require('NavigationPropTypes');
-const React = require('React');
+const React = require('react-native');
const ReactComponentWithPureRenderMixin = require('ReactComponentWithPureRenderMixin');
const StyleSheet = require('StyleSheet');
const View = require('View');
-const {Directions} = NavigationLinearPanResponder;
-
import type {
- NavigationAnimatedValue,
- NavigationLayout,
- NavigationPosition,
+ NavigationPanPanHandlers,
NavigationSceneRenderer,
NavigationSceneRendererProps,
} from 'NavigationTypeDefinition';
-import type {
- NavigationGestureDirection
-} from 'NavigationLinearPanResponder';
-
-type State = {
- hash: string,
- height: number,
- width: number,
-};
-
type Props = NavigationSceneRendererProps & {
- direction: NavigationGestureDirection,
+ style: any,
+ panHandlers: ?NavigationPanPanHandlers,
renderScene: NavigationSceneRenderer,
};
@@ -65,78 +58,18 @@ const {PropTypes} = React;
const propTypes = {
...NavigationPropTypes.SceneRenderer,
- direction: PropTypes.oneOf([Directions.HORIZONTAL, Directions.VERTICAL]),
+ style: PropTypes.any,
+ panHandlers: NavigationPropTypes.panHandlers,
renderScene: PropTypes.func.isRequired,
};
-const defaultProps = {
- direction: Directions.HORIZONTAL,
-};
-
-class AmimatedValueSubscription {
- _value: NavigationAnimatedValue;
- _token: string;
-
- constructor(value: NavigationAnimatedValue, callback: Function) {
- this._value = value;
- this._token = value.addListener(callback);
- }
-
- remove() {
- this._value.removeListener(this._token);
- }
-}
-
-/**
- * Class that provides the required information for the
- * `NavigationLinearPanResponder`. This class must implement
- * the interface `NavigationLinearPanResponderDelegate`.
- */
-class PanResponderDelegate {
- _props : Props;
-
- constructor(props: Props) {
- this._props = props;
- }
-
- getDirection(): NavigationGestureDirection {
- return this._props.direction;
- }
-
- getIndex(): number {
- return this._props.navigationState.index;
- }
-
- getLayout(): NavigationLayout {
- return this._props.layout;
- }
-
- getPosition(): NavigationPosition {
- return this._props.position;
- }
-
- onNavigate(action: {type: string}): void {
- this._props.onNavigate && this._props.onNavigate(action);
- }
-}
-
/**
* Component that renders the scene as card for the .
*/
-class NavigationCard extends React.Component {
+class NavigationCard extends React.Component {
props: Props;
- state: State;
- _calculateState: (t: NavigationLayout) => State;
- _layoutListeners: Array;
-
- constructor(props: Props, context: any) {
- super(props, context);
-
- this.state = this._calculateState(props.layout);
- this._layoutListeners = [];
- }
- shouldComponentUpdate(nextProps: Object, nextState: Object): boolean {
+ shouldComponentUpdate(nextProps: Props, nextState: any): boolean {
return ReactComponentWithPureRenderMixin.shouldComponentUpdate.call(
this,
nextProps,
@@ -144,130 +77,32 @@ class NavigationCard extends React.Component {
);
}
- componentWillMount(): void {
- this._calculateState = this._calculateState.bind(this);
- }
-
- componentDidMount(): void {
- this._applyLayout(this.props.layout);
- }
-
- componentWillUnmount(): void {
- this._layoutListeners.forEach(subscription => subscription.remove);
- }
-
- componentWillReceiveProps(nextProps: Props): void {
- this._applyLayout(nextProps.layout);
- }
-
render(): ReactElement {
- const {
- direction,
- layout,
- navigationState,
- onNavigate,
- position,
- scene,
- scenes,
+ let {
+ style,
+ panHandlers,
+ renderScene,
+ ...props,
} = this.props;
- const {
- height,
- width,
- } = this.state;
-
- const index = scene.index;
- const isVertical = direction === 'vertical';
- const inputRange = [index - 1, index, index + 1];
- const animatedStyle = {
-
- opacity: position.interpolate({
- inputRange,
- outputRange: [1, 1, 0.3],
- }),
-
- transform: [
- {
- scale: position.interpolate({
- inputRange,
- outputRange: [1, 1, 0.95],
- }),
- },
- {
- translateX: isVertical ? 0 :
- position.interpolate({
- inputRange,
- outputRange: [width, 0, -10],
- }),
- },
- {
- translateY: !isVertical ? 0 :
- position.interpolate({
- inputRange,
- outputRange: [height, 0, -10],
- }),
- },
- ],
- };
-
- let panHandlers = null;
- if (navigationState.index === index) {
- const delegate = new PanResponderDelegate(this.props);
- const panResponder = new NavigationLinearPanResponder(delegate);
- panHandlers = panResponder.panHandlers;
+ if (style === undefined) {
+ // fall back to default style.
+ style = NavigationCardStackStyleInterpolator.forHorizontal(props);
+ }
+ if (panHandlers === undefined) {
+ // fall back to default pan handlers.
+ panHandlers = NavigationLinearPanResponder.forHorizontal(props);
}
-
- const sceneProps = {
- layout,
- navigationState,
- onNavigate,
- position,
- scene,
- scenes,
- };
return (
-
- {this.props.renderScene(sceneProps)}
+
+ {renderScene(props)}
);
}
-
- _calculateState(layout: NavigationLayout): State {
- const width = layout.width.__getValue();
- const height = layout.height.__getValue();
- const hash = 'layout-' + width + '-' + height;
- const state = {
- height,
- width,
- hash,
- };
- return state;
- }
-
- _applyLayout(layout: NavigationLayout) {
- this._layoutListeners.forEach(subscription => subscription.remove);
-
- this._layoutListeners.length = 0;
-
- const callback = this._applyLayout.bind(this, layout);
-
- this._layoutListeners.push(
- new AmimatedValueSubscription(layout.width, callback),
- new AmimatedValueSubscription(layout.height, callback),
- );
-
- const nextState = this._calculateState(layout);
- if (nextState.hash !== this.state.hash) {
- this.setState(nextState);
- }
- }
}
NavigationCard.propTypes = propTypes;
-NavigationCard.defaultProps = defaultProps;
const styles = StyleSheet.create({
main: {
diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationCardStack.js b/Libraries/CustomComponents/NavigationExperimental/NavigationCardStack.js
index 8b6cc316d4fbae..319d8d721b9545 100644
--- a/Libraries/CustomComponents/NavigationExperimental/NavigationCardStack.js
+++ b/Libraries/CustomComponents/NavigationExperimental/NavigationCardStack.js
@@ -1,5 +1,10 @@
/**
- * Copyright (c) 2015, Facebook, Inc. All rights reserved.
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* Facebook, Inc. ("Facebook") owns all right, title and interest, including
* all intellectual property and other proprietary rights, in and to the React
@@ -30,6 +35,7 @@
const Animated = require('Animated');
const NavigationAnimatedView = require('NavigationAnimatedView');
const NavigationCard = require('NavigationCard');
+const NavigationCardStackStyleInterpolator = require('NavigationCardStackStyleInterpolator');
const NavigationContainer = require('NavigationContainer');
const NavigationLinearPanResponder = require('NavigationLinearPanResponder');
const NavigationPropTypes = require('NavigationPropTypes');
@@ -110,12 +116,23 @@ class NavigationCardStack extends React.Component {
}
_renderScene(props: NavigationSceneRendererProps): ReactElement {
+ const isVertical = this.props.direction === 'vertical';
+
+ const style = isVertical ?
+ NavigationCardStackStyleInterpolator.forVertical(props) :
+ NavigationCardStackStyleInterpolator.forHorizontal(props);
+
+ const panHandlers = isVertical ?
+ NavigationLinearPanResponder.forVertical(props) :
+ NavigationLinearPanResponder.forHorizontal(props);
+
return (
);
}
diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationCardStackStyleInterpolator.js b/Libraries/CustomComponents/NavigationExperimental/NavigationCardStackStyleInterpolator.js
new file mode 100644
index 00000000000000..d4b65644ac7030
--- /dev/null
+++ b/Libraries/CustomComponents/NavigationExperimental/NavigationCardStackStyleInterpolator.js
@@ -0,0 +1,121 @@
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * Facebook, Inc. ("Facebook") owns all right, title and interest, including
+ * all intellectual property and other proprietary rights, in and to the React
+ * Native CustomComponents software (the "Software"). Subject to your
+ * compliance with these terms, you are hereby granted a non-exclusive,
+ * worldwide, royalty-free copyright license to (1) use and copy the Software;
+ * and (2) reproduce and distribute the Software as part of your own software
+ * ("Your Software"). Facebook reserves all rights not expressly granted to
+ * you in this license agreement.
+ *
+ * THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED.
+ * IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR
+ * EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @providesModule NavigationCardStackStyleInterpolator
+ * @flow
+ */
+'use strict';
+
+/**
+ * Predefined interpolator that renders the animated style for NavigationCard.
+ *
+ */
+
+import type {
+ NavigationSceneRendererProps,
+} from 'NavigationTypeDefinition';
+
+function forHorizontal(props: NavigationSceneRendererProps): Object {
+ const {
+ layout,
+ position,
+ scene,
+ } = props;
+
+ const index = scene.index;
+ const inputRange = [index - 1, index, index + 1];
+ const width = layout.initWidth;
+
+ const opacity = position.interpolate({
+ inputRange,
+ outputRange: [1, 1, 0.3],
+ });
+
+ const scale = position.interpolate({
+ inputRange,
+ outputRange: [1, 1, 0.95],
+ });
+
+ const translateY = 0;
+ const translateX = position.interpolate({
+ inputRange,
+ outputRange: [width, 0, -10],
+ });
+
+ return {
+ opacity,
+ transform: [
+ { scale },
+ { translateX },
+ { translateY },
+ ],
+ };
+}
+
+function forVertical(props: NavigationSceneRendererProps): Object {
+ const {
+ layout,
+ position,
+ scene,
+ } = props;
+
+ const index = scene.index;
+ const inputRange = [index - 1, index, index + 1];
+ const height = layout.initHeight;
+
+ const opacity = position.interpolate({
+ inputRange,
+ outputRange: [1, 1, 0.3],
+ });
+
+ const scale = position.interpolate({
+ inputRange,
+ outputRange: [1, 1, 0.95],
+ });
+
+ const translateX = 0;
+ const translateY = position.interpolate({
+ inputRange,
+ outputRange: [height, 0, -10],
+ });
+
+ return {
+ opacity,
+ transform: [
+ { scale },
+ { translateX },
+ { translateY },
+ ],
+ };
+}
+
+module.exports = {
+ forHorizontal,
+ forVertical,
+};
diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationLegacyNavigator.js b/Libraries/CustomComponents/NavigationExperimental/NavigationLegacyNavigator.js
index 6f1909db89e59f..bbb0221a8d2095 100644
--- a/Libraries/CustomComponents/NavigationExperimental/NavigationLegacyNavigator.js
+++ b/Libraries/CustomComponents/NavigationExperimental/NavigationLegacyNavigator.js
@@ -1,5 +1,10 @@
/**
- * Copyright (c) 2015, Facebook, Inc. All rights reserved.
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* Facebook, Inc. ("Facebook") owns all right, title and interest, including
* all intellectual property and other proprietary rights, in and to the React
@@ -30,8 +35,10 @@
const NavigationAnimatedValueSubscription = require('NavigationAnimatedValueSubscription');
const NavigationAnimatedView = require('NavigationAnimatedView');
const NavigationCard = require('NavigationCard');
+const NavigationCardStackStyleInterpolator = require('NavigationCardStackStyleInterpolator');
const NavigationContext = require('NavigationContext');
const NavigationLegacyNavigatorRouteStack = require('NavigationLegacyNavigatorRouteStack');
+const NavigationLinearPanResponder = require('NavigationLinearPanResponder');
const NavigatorBreadcrumbNavigationBar = require('NavigatorBreadcrumbNavigationBar');
const NavigatorNavigationBar = require('NavigatorNavigationBar');
const NavigatorSceneConfigs = require('NavigatorSceneConfigs');
@@ -287,38 +294,48 @@ class NavigationLegacyNavigator extends React.Component {
}
_renderCard(props: NavigationSceneRendererProps): ReactElement {
- let direction = 'horizontal';
-
- const {navigationState} = props.scene;
+ const {scene} = props;
const {configureScene} = this.props;
+ let isVertical = false;
+
if (configureScene) {
- const route = RouteStack.getRouteByNavigationState(navigationState);
+ const route = RouteStack.getRouteByNavigationState(scene.navigationState);
const config = configureScene(route, this.state.routeStack);
+ const direction = getConfigPopDirection(config);
- switch (getConfigPopDirection(config)) {
+ switch (direction) {
case 'left-to-right':
- direction = 'horizontal';
+ // default.
break;
case 'top-to-bottom':
- direction = 'vertical';
+ isVertical = true;
break;
default:
// unsupported config.
if (__DEV__) {
- console.warn('unsupported scene configuration');
+ console.warn('unsupported scene configuration %s', direction);
}
}
}
+ const style = isVertical ?
+ NavigationCardStackStyleInterpolator.forVertical(props) :
+ NavigationCardStackStyleInterpolator.forHorizontal(props);
+
+ const panHandlers = isVertical ?
+ NavigationLinearPanResponder.forVertical(props) :
+ NavigationLinearPanResponder.forHorizontal(props);
+
return (
);
}
diff --git a/Libraries/NavigationExperimental/NavigationAbstractPanResponder.js b/Libraries/NavigationExperimental/NavigationAbstractPanResponder.js
index 98fdbf32d0055f..cd31dccdbde158 100644
--- a/Libraries/NavigationExperimental/NavigationAbstractPanResponder.js
+++ b/Libraries/NavigationExperimental/NavigationAbstractPanResponder.js
@@ -1,5 +1,10 @@
/**
- * Copyright 2004-present Facebook. All Rights Reserved.
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule NavigationAbstractPanResponder
* @flow
@@ -10,6 +15,10 @@ const PanResponder = require('PanResponder');
const invariant = require('fbjs/lib/invariant');
+import type {
+ NavigationPanPanHandlers,
+} from 'NavigationTypeDefinition';
+
const EmptyPanHandlers = {
onMoveShouldSetPanResponder: null,
onPanResponderGrant: null,
@@ -24,7 +33,7 @@ const EmptyPanHandlers = {
*/
class NavigationAbstractPanResponder {
- panHandlers: Object;
+ panHandlers: NavigationPanPanHandlers;
constructor() {
const config = {};
diff --git a/Libraries/NavigationExperimental/NavigationExperimental.js b/Libraries/NavigationExperimental/NavigationExperimental.js
index ca6bb627d5597b..e30fa3a8380fe2 100644
--- a/Libraries/NavigationExperimental/NavigationExperimental.js
+++ b/Libraries/NavigationExperimental/NavigationExperimental.js
@@ -14,9 +14,11 @@
const NavigationAnimatedView = require('NavigationAnimatedView');
const NavigationCard = require('NavigationCard');
const NavigationCardStack = require('NavigationCardStack');
+const NavigationCardStackStyleInterpolator = require('NavigationCardStackStyleInterpolator');
const NavigationContainer = require('NavigationContainer');
const NavigationHeader = require('NavigationHeader');
const NavigationLegacyNavigator = require('NavigationLegacyNavigator');
+const NavigationLinearPanResponder = require('NavigationLinearPanResponder');
const NavigationReducer = require('NavigationReducer');
const NavigationRootContainer = require('NavigationRootContainer');
const NavigationStateUtils = require('NavigationStateUtils');
@@ -40,6 +42,12 @@ const NavigationExperimental = {
CardStack: NavigationCardStack,
Header: NavigationHeader,
LegacyNavigator: NavigationLegacyNavigator,
+
+ // Animations Style Interpolators:
+ CardStackStyleInterpolator: NavigationCardStackStyleInterpolator,
+
+ // Interactions:
+ LinearPanResponder: NavigationLinearPanResponder,
};
module.exports = NavigationExperimental;
diff --git a/Libraries/NavigationExperimental/NavigationLinearPanResponder.js b/Libraries/NavigationExperimental/NavigationLinearPanResponder.js
index 2318a70c6ca30c..94b23ea9e291ee 100644
--- a/Libraries/NavigationExperimental/NavigationLinearPanResponder.js
+++ b/Libraries/NavigationExperimental/NavigationLinearPanResponder.js
@@ -1,5 +1,10 @@
/**
- * Copyright 2004-present Facebook. All Rights Reserved.
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule NavigationLinearPanResponder
* @flow
@@ -13,9 +18,8 @@ const NavigationAbstractPanResponder = require('NavigationAbstractPanResponder')
const clamp = require('clamp');
import type {
- NavigationActionCaller,
- NavigationLayout,
- NavigationPosition,
+ NavigationPanPanHandlers,
+ NavigationSceneRendererProps,
} from 'NavigationTypeDefinition';
/**
@@ -36,9 +40,9 @@ const POSITION_THRESHOLD = 1 / 3;
const RESPOND_THRESHOLD = 15;
/**
- * The threshold (in speed) to finish the gesture action.
+ * The threshold (in pixels) to finish the gesture action.
*/
-const VELOCITY_THRESHOLD = 100;
+const DISTANCE_THRESHOLD = 100;
/**
* Primitive gesture directions.
@@ -48,7 +52,7 @@ const Directions = {
'VERTICAL': 'vertical',
};
-export type NavigationGestureDirection = $Enum;
+export type NavigationGestureDirection = 'horizontal' | 'vertical';
/**
* Primitive gesture actions.
@@ -60,43 +64,39 @@ const Actions = {
BACK: {type: 'back'},
};
-/**
- * The type interface of the object that provides the information required by
- * NavigationLinearPanResponder.
- */
-export type NavigationLinearPanResponderDelegate = {
- getDirection: () => NavigationGestureDirection;
- getIndex: () => number,
- getLayout: () => NavigationLayout,
- getPosition: () => NavigationPosition,
- onNavigate: NavigationActionCaller,
-};
-
/**
* Pan responder that handles the One-dimensional gesture (horizontal or
* vertical).
*/
class NavigationLinearPanResponder extends NavigationAbstractPanResponder {
- static Actions: Object;
- static Directions: Object;
_isResponding: boolean;
+ _isVertical: boolean;
+ _props: NavigationSceneRendererProps;
_startValue: number;
- _delegate: NavigationLinearPanResponderDelegate;
- constructor(delegate: NavigationLinearPanResponderDelegate) {
+ constructor(
+ direction: NavigationGestureDirection,
+ props: NavigationSceneRendererProps,
+ ) {
super();
this._isResponding = false;
+ this._isVertical = direction === Directions.VERTICAL;
+ this._props = props;
this._startValue = 0;
- this._delegate = delegate;
}
onMoveShouldSetPanResponder(event: any, gesture: any): boolean {
- const delegate = this._delegate;
- const layout = delegate.getLayout();
- const isVertical = delegate.getDirection() === Directions.VERTICAL;
+ const props = this._props;
+
+ if (props.navigationState.index !== props.scene.index) {
+ return false;
+ }
+
+ const layout = props.layout;
+ const isVertical = this._isVertical;
const axis = isVertical ? 'dy' : 'dx';
- const index = delegate.getIndex();
+ const index = props.navigationState.index;
const distance = isVertical ?
layout.height.__getValue() :
layout.width.__getValue();
@@ -110,7 +110,7 @@ class NavigationLinearPanResponder extends NavigationAbstractPanResponder {
onPanResponderGrant(): void {
this._isResponding = false;
- this._delegate.getPosition().stopAnimation((value: number) => {
+ this._props.position.stopAnimation((value: number) => {
this._isResponding = true;
this._startValue = value;
});
@@ -121,11 +121,11 @@ class NavigationLinearPanResponder extends NavigationAbstractPanResponder {
return;
}
- const delegate = this._delegate;
- const layout = delegate.getLayout();
- const isVertical = delegate.getDirection() === Directions.VERTICAL;
+ const props = this._props;
+ const layout = props.layout;
+ const isVertical = this._isVertical;
const axis = isVertical ? 'dy' : 'dx';
- const index = delegate.getIndex();
+ const index = props.navigationState.index;
const distance = isVertical ?
layout.height.__getValue() :
layout.width.__getValue();
@@ -136,7 +136,7 @@ class NavigationLinearPanResponder extends NavigationAbstractPanResponder {
index
);
- this._delegate.getPosition().setValue(value);
+ props.position.setValue(value);
}
onPanResponderRelease(event: any, gesture: any): void {
@@ -146,16 +146,16 @@ class NavigationLinearPanResponder extends NavigationAbstractPanResponder {
this._isResponding = false;
- const delegate = this._delegate;
- const isVertical = delegate.getDirection() === Directions.VERTICAL;
+ const props = this._props;
+ const isVertical = this._isVertical;
const axis = isVertical ? 'dy' : 'dx';
- const index = delegate.getIndex();
- const velocity = gesture[axis];
+ const index = props.navigationState.index;
+ const distance = gesture[axis];
- delegate.getPosition().stopAnimation((value: number) => {
+ props.position.stopAnimation((value: number) => {
this._reset();
- if (velocity > VELOCITY_THRESHOLD || value <= index - POSITION_THRESHOLD) {
- delegate.onNavigate(Actions.BACK);
+ if (distance > DISTANCE_THRESHOLD || value <= index - POSITION_THRESHOLD) {
+ props.onNavigate(Actions.BACK);
}
});
}
@@ -166,17 +166,40 @@ class NavigationLinearPanResponder extends NavigationAbstractPanResponder {
}
_reset(): void {
+ const props = this._props;
Animated.timing(
- this._delegate.getPosition(),
+ props.position,
{
- toValue: this._delegate.getIndex(),
+ toValue: props.navigationState.index,
duration: ANIMATION_DURATION,
}
).start();
}
}
-NavigationLinearPanResponder.Actions = Actions;
-NavigationLinearPanResponder.Directions = Directions;
+function createPanHandlers(
+ direction: NavigationGestureDirection,
+ props: NavigationSceneRendererProps,
+): NavigationPanPanHandlers {
+ const responder = new NavigationLinearPanResponder(direction, props);
+ return responder.panHandlers;
+}
+
+function forHorizontal(
+ props: NavigationSceneRendererProps,
+): NavigationPanPanHandlers {
+ return createPanHandlers(Directions.HORIZONTAL, props);
+}
-module.exports = NavigationLinearPanResponder;
+function forVertical(
+ props: NavigationSceneRendererProps,
+): NavigationPanPanHandlers {
+ return createPanHandlers(Directions.VERTICAL, props);
+}
+
+module.exports = {
+ Actions,
+ Directions,
+ forHorizontal,
+ forVertical,
+};
diff --git a/Libraries/NavigationExperimental/NavigationPropTypes.js b/Libraries/NavigationExperimental/NavigationPropTypes.js
index b5d87834199644..841895f51014f9 100644
--- a/Libraries/NavigationExperimental/NavigationPropTypes.js
+++ b/Libraries/NavigationExperimental/NavigationPropTypes.js
@@ -68,9 +68,26 @@ const SceneRenderer = {
scenes: PropTypes.arrayOf(scene).isRequired,
};
+/* NavigationPanPanHandlers */
+const panHandlers = PropTypes.shape({
+ onMoveShouldSetResponder: PropTypes.func.isRequired,
+ onMoveShouldSetResponderCapture: PropTypes.func.isRequired,
+ onResponderEnd: PropTypes.func.isRequired,
+ onResponderGrant: PropTypes.func.isRequired,
+ onResponderMove: PropTypes.func.isRequired,
+ onResponderReject: PropTypes.func.isRequired,
+ onResponderRelease: PropTypes.func.isRequired,
+ onResponderStart: PropTypes.func.isRequired,
+ onResponderTerminate: PropTypes.func.isRequired,
+ onResponderTerminationRequest: PropTypes.func.isRequired,
+ onStartShouldSetResponder: PropTypes.func.isRequired,
+ onStartShouldSetResponderCapture: PropTypes.func.isRequired,
+});
+
module.exports = {
SceneRenderer,
action,
navigationParentState,
navigationState,
+ panHandlers,
};
diff --git a/Libraries/NavigationExperimental/NavigationTypeDefinition.js b/Libraries/NavigationExperimental/NavigationTypeDefinition.js
index 3f6f6e43922af1..6ecd2774bf7f7f 100644
--- a/Libraries/NavigationExperimental/NavigationTypeDefinition.js
+++ b/Libraries/NavigationExperimental/NavigationTypeDefinition.js
@@ -68,6 +68,21 @@ export type NavigationSceneRendererProps = {
scenes: Array,
};
+export type NavigationPanPanHandlers = {
+ onMoveShouldSetResponder: Function,
+ onMoveShouldSetResponderCapture: Function,
+ onResponderEnd: Function,
+ onResponderGrant: Function,
+ onResponderMove: Function,
+ onResponderReject: Function,
+ onResponderRelease: Function,
+ onResponderStart: Function,
+ onResponderTerminate: Function,
+ onResponderTerminationRequest: Function,
+ onStartShouldSetResponder: Function,
+ onStartShouldSetResponderCapture: Function,
+};
+
// Functions.
export type NavigationActionCaller = Function;