diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js index 54285d01a..7046d6a21 100644 --- a/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js +++ b/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js @@ -35,6 +35,7 @@ const View = require('View'); const EXAMPLES = { 'CardStack + Header + Tabs Example': require('./NavigationCardStack-NavigationHeader-Tabs-example'), 'CardStack Example': require('./NavigationCardStack-example'), + 'Transitioner + Animated View Example': require('./NavigationTransitioner-AnimatedView-example'), }; const EXAMPLE_STORAGE_KEY = 'NavigationExperimentalExample'; diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationTransitioner-AnimatedView-example.js b/Examples/UIExplorer/NavigationExperimental/NavigationTransitioner-AnimatedView-example.js new file mode 100644 index 000000000..31cafcb91 --- /dev/null +++ b/Examples/UIExplorer/NavigationExperimental/NavigationTransitioner-AnimatedView-example.js @@ -0,0 +1,255 @@ +/** + * 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. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * @flow + */ +'use strict'; + +const NavigationExampleRow = require('./NavigationExampleRow'); +const React = require('react'); +const ReactNative = require('react-native'); + +/** + * Basic example that shows how to use and + * to build a stack of animated scenes that render the + * navigation state. + */ + + +import type { + NavigationSceneRendererProps, + NavigationState, + NavigationTransitionProps, + NavigationTransitionSpec, +} from 'NavigationTypeDefinition'; + +const { + Component, + PropTypes, +} = React; + +const { + Animated, + Easing, + NavigationExperimental, + ScrollView, + StyleSheet, +} = ReactNative; + +const { + PropTypes: NavigationPropTypes, + StateUtils: NavigationStateUtils, + Transitioner: NavigationTransitioner, +} = NavigationExperimental; + +function reducer(state: ?NavigationState, action: any): NavigationState { + if (!state) { + return { + index: 0, + routes: [{key: 'route-1'}], + }; + } + + switch (action) { + case 'push': + const route = {key: 'route-' + (state.routes.length + 1)}; + return NavigationStateUtils.push(state, route); + case 'pop': + return NavigationStateUtils.pop(state); + } + return state; +} + +class Example extends Component { + state: NavigationState; + constructor(props: any, context: any) { + super(props, context); + this.state = reducer(); + } + + render(): ReactElement { + return ( + this._navigate(action)} + /> + ); + } + + _navigate(action: any): boolean { + if (action === 'exit') { + // Exits the example. `this.props.onExampleExit` is provided + // by the UI Explorer. + this.props.onExampleExit && this.props.onExampleExit(); + return false; + } + + const state = reducer(this.state, action); + if (state === this.state) { + return false; + } + + this.setState(state); + return true; + } + + // This public method is optional. If exists, the UI explorer will call it + // the "back button" is pressed. Normally this is the cases for Android only. + handleBackAction(): boolean { + return this._navigate('pop'); + } +} + +class ExampleNavigator extends Component { + props: { + navigate: Function, + navigationState: NavigationState, + }; + + static propTypes: { + navigationState: NavigationPropTypes.navigationState.isRequired, + navigate: PropTypes.func.isRequired, + }; + + render(): ReactElement { + return ( + this._render(transitionProps)} + configureTransition={this._configureTransition} + /> + ); + } + + _render( + transitionProps: NavigationTransitionProps, + ): Array> { + return transitionProps.scenes.map((scene) => { + const sceneProps = { + ...transitionProps, + scene, + }; + return this._renderScene(sceneProps); + }); + } + + _renderScene( + sceneProps: NavigationSceneRendererProps, + ): ReactElement { + return ( + + ); + } + + _configureTransition(): NavigationTransitionSpec { + const easing: any = Easing.inOut(Easing.ease); + return { + duration: 500, + easing, + }; + } +} + +class ExampleScene extends Component { + props: NavigationSceneRendererProps & { + navigate: Function, + }; + + static propTypes = { + ...NavigationPropTypes.SceneRendererProps, + navigate: PropTypes.func.isRequired, + }; + + render(): ReactElement { + const {scene, navigate} = this.props; + return ( + + + + navigate('push')} + /> + navigate('pop')} + /> + navigate('exit')} + /> + + + ); + } + + _getAnimatedStyle(): Object { + const { + layout, + position, + scene, + } = this.props; + + const { + index, + } = scene; + + const inputRange = [index - 1, index, index + 1]; + const width = layout.initWidth; + const translateX = position.interpolate({ + inputRange, + outputRange: [width, 0, -10], + }); + + return { + transform: [ + { translateX }, + ], + }; + } +} + +const styles = StyleSheet.create({ + scene: { + backgroundColor: '#E9E9EF', + bottom: 0, + flex: 1, + left: 0, + position: 'absolute', + right: 0, + shadowColor: 'black', + shadowOffset: {width: 0, height: 0}, + shadowOpacity: 0.4, + shadowRadius: 10, + top: 0, + }, + scrollView: { + flex: 1, + }, +}); + +module.exports = Example;