Skip to content

Commit

Permalink
Clean up NavigationView.
Browse files Browse the repository at this point in the history
Summary:This address the issue reported at
#6579 (comment)

NavigationView should have the same API as NavigationAnimatedView does except
that NavigationView does not need the APIs for animation.

This unify the API of our core components so that people can freely
compose views with both NavigationAnimatedView or NavigationView.

Reviewed By: fkgozali

Differential Revision: D3096076

fb-gh-sync-id: 7536777a7d637da62a2636d750f9d91c5a0eb45f
fbshipit-source-id: 7536777a7d637da62a2636d750f9d91c5a0eb45f
  • Loading branch information
Hedger Wang authored and Facebook Github Bot 9 committed Mar 29, 2016
1 parent 97d15f7 commit 68918e8
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -265,21 +265,33 @@ class NavigationCompositionExample extends React.Component {
}

class ExampleMainView extends React.Component {
_renderScene: NavigationSceneRenderer;

componentWillMount() {
this._renderScene = this._renderScene.bind(this);
}

render() {
return (
<NavigationView
navigationState={this.props.navigationState}
style={styles.tabsContent}
renderScene={(tabState, index) => (
<ExampleTabScreen
key={tabState.key}
navigationState={tabState}
onNavigate={this._handleNavigation.bind(this, tabState.key)}
/>
)}
renderScene={this._renderScene}
/>
);
}

_renderScene(props: NavigationSceneRendererProps): ReactElement {
const {scene} = props;
return (
<ExampleTabScreen
key={'tab_screen' + scene.key}
navigationState={scene.navigationState}
onNavigate={this._handleNavigation.bind(this, scene.key)}
/>
);
}

_handleNavigation(tabKey, action) {
if (ExampleExitAction.match(action)) {
this.props.onExampleExit();
Expand All @@ -288,6 +300,7 @@ class ExampleMainView extends React.Component {
this.props.onNavigate(action);
}
}

ExampleMainView = NavigationContainer.create(ExampleMainView);

const styles = StyleSheet.create({
Expand Down
3 changes: 2 additions & 1 deletion Libraries/NavigationExperimental/NavigationAnimatedView.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const StyleSheet = require('StyleSheet');
const View = require('View');

import type {
NavigationActionCaller,
NavigationAnimatedValue,
NavigationAnimationSetter,
NavigationLayout,
Expand All @@ -31,7 +32,7 @@ import type {
type Props = {
applyAnimation: NavigationAnimationSetter,
navigationState: NavigationParentState,
onNavigate: (action: any) => void,
onNavigate: NavigationActionCaller,
renderOverlay: ?NavigationSceneRenderer,
renderScene: NavigationSceneRenderer,
style: any,
Expand Down
183 changes: 148 additions & 35 deletions Libraries/NavigationExperimental/NavigationView.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,51 +11,164 @@
*/
'use strict';

var React = require('React');
var NavigationContainer = require('NavigationContainer');
var StyleSheet = require('StyleSheet');
var View = require('View');

var NavigationView = React.createClass({
propTypes: {
// todo, figure out a propType for getK
navigationState: React.PropTypes.object.isRequired,
renderScene: React.PropTypes.func.isRequired,
},
render: function() {
return (
<View
style={this.props.style}>
{this.props.navigationState.children.map(this._renderScene)}
</View>
const Animated = require('Animated');
const NavigationContainer = require('NavigationContainer');
const React = require('react-native');
const StyleSheet = require('StyleSheet');
const View = require('View');
const NavigationScenesReducer = require('NavigationScenesReducer');
const ReactComponentWithPureRenderMixin = require('ReactComponentWithPureRenderMixin');

import type {
NavigationActionCaller,
NavigationAnimatedValue,
NavigationLayout,
NavigationParentState,
NavigationScene,
NavigationSceneRenderer,
NavigationSceneRendererProps,
} from 'NavigationTypeDefinition';

type Props = {
navigationState: NavigationParentState,
onNavigate: NavigationActionCaller,
renderScene: NavigationSceneRenderer,
style: any,
};

type State = {
scenes: Array<NavigationScene>,
};

const {PropTypes} = React;

/**
* A simple view that will render a scene for the currently focused sub-state.
* The most common use-case is for tabs, where no transition is needed
*/
class NavigationView extends React.Component<any, Props, any> {
_layout: NavigationLayout;
_onLayout: (event: any) => void;
_position: NavigationAnimatedValue;

props: Props;
state: State;

static propTypes = {
navigationState: PropTypes.object.isRequired,
onNavigate: PropTypes.func.isRequired,
renderScene: PropTypes.func.isRequired,
};

constructor(props: Props, context: any) {
super(props, context);

this._layout = {
initWidth: 0,
initHeight: 0,
width: new Animated.Value(0),
height: new Animated.Value(0),
};

const {navigationState} = this.props;

this._position = new Animated.Value(navigationState.index);

this.state = {
scenes: NavigationScenesReducer([], navigationState),
};
}

shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
return ReactComponentWithPureRenderMixin.shouldComponentUpdate.call(
this,
nextProps,
nextState
);
},
_renderScene: function(route, index) {
var isSelected = index === this.props.navigationState.index;
}

componentWillReceiveProps(nextProps: Props): void {
if (nextProps.navigationState !== this.props.navigationState) {
const {navigationState} = nextProps;
this.setState(
{
scenes: NavigationScenesReducer(
this.state.scenes,
navigationState,
null, // There will be no transtion.
),
},
() => {
this._position.setValue(navigationState.index);
},
);
}
}

componentWillMount(): void {
this._onLayout = this._onLayout.bind(this);
}

render(): ReactElement {
const {
navigationState,
onNavigate
} = this.props;

const {
scenes,
} = this.state;

const sceneProps = {
layout: this._layout,
navigationState: navigationState,
onNavigate: onNavigate,
position: this._position,
scene: scenes[navigationState.index],
scenes,
};

return (
<View
key={route.key}
pointerEvents={isSelected ? 'auto' : 'none'}
style={[
styles.navView,
{opacity: isSelected ? 1 : 0},
]}>
{this.props.renderScene(route, index)}
onLayout={this._onLayout}
style={this.props.style}>
{this._renderScene(sceneProps)}
</View>
);
},
});
}

NavigationView = NavigationContainer.create(NavigationView);
_renderScene(props: NavigationSceneRendererProps): ?ReactElement {

var styles = StyleSheet.create({
navView: {
position: 'absolute',
const child = this.props.renderScene(props);
if (child === null) {
return null;
}
return <View key={props.scene.key} style={styles.scene}>{child}</View>;
}

_onLayout(event: any): void {
const {height, width} = event.nativeEvent.layout;

const layout = {
...this._layout,
initHeight: height,
initWidth: width,
};

this._layout = layout;
layout.height.setValue(height);
layout.width.setValue(width);
}
}

const styles = StyleSheet.create({
scene: {
bottom: 0,
left: 0,
position: 'absolute',
right: 0,
top: 0,
bottom: 0,
},
});

module.exports = NavigationView;
module.exports = NavigationContainer.create(NavigationView);

0 comments on commit 68918e8

Please sign in to comment.