Define the generic render prop for NavigationTransitioner to render scenes.

Summary:
This defines the generic function prop `render(props: NavigationTransitionProps)`
to NavigationTransitioner, which enables developer to render scenes, header, overlay,
underlay...etc.

Differential Revision: D3431478

fbshipit-source-id: 93dbc7da23ad8c95565b01f7865d1e8dfd4401f7
This commit is contained in:
Hedger Wang 2016-06-14 16:41:59 -07:00 committed by Facebook Github Bot 7
parent 4ab1bcb124
commit 3a6231432a
2 changed files with 43 additions and 84 deletions

View File

@ -19,15 +19,13 @@ const React = require('React');
const StyleSheet = require('StyleSheet'); const StyleSheet = require('StyleSheet');
const View = require('View'); const View = require('View');
const invariant = require('fbjs/lib/invariant');
import type { import type {
NavigationAnimatedValue, NavigationAnimatedValue,
NavigationLayout, NavigationLayout,
NavigationState,
NavigationScene, NavigationScene,
NavigationSceneRenderer, NavigationState,
NavigationTransitionConfigurator, NavigationTransitionConfigurator,
NavigationTransitionProps,
} from 'NavigationTypeDefinition'; } from 'NavigationTypeDefinition';
type Props = { type Props = {
@ -35,8 +33,7 @@ type Props = {
navigationState: NavigationState, navigationState: NavigationState,
onTransitionEnd: () => void, onTransitionEnd: () => void,
onTransitionStart: () => void, onTransitionStart: () => void,
renderOverlay: ?NavigationSceneRenderer, render: (props: NavigationTransitionProps) => any,
renderScene: NavigationSceneRenderer,
style: any, style: any,
}; };
@ -71,8 +68,7 @@ class NavigationTransitioner extends React.Component<any, Props, State> {
navigationState: NavigationPropTypes.navigationState.isRequired, navigationState: NavigationPropTypes.navigationState.isRequired,
onTransitionEnd: PropTypes.func, onTransitionEnd: PropTypes.func,
onTransitionStart: PropTypes.func, onTransitionStart: PropTypes.func,
renderOverlay: PropTypes.func, render: PropTypes.func.isRequired,
renderScene: PropTypes.func.isRequired,
}; };
constructor(props: Props, context: any) { constructor(props: Props, context: any) {
@ -162,81 +158,15 @@ class NavigationTransitioner extends React.Component<any, Props, State> {
} }
render(): ReactElement<any> { render(): ReactElement<any> {
const overlay = this._renderOverlay();
const scenes = this._renderScenes();
return ( return (
<View <View
onLayout={this._onLayout} onLayout={this._onLayout}
style={this.props.style}> style={[styles.main, this.props.style]}>
<View style={styles.scenes} key="scenes"> {this.props.render(this._buildTransitionProps())}
{scenes}
</View>
{overlay}
</View> </View>
); );
} }
_renderScenes(): Array<?ReactElement<any>> {
return this.state.scenes.map(this._renderScene, this);
}
_renderScene(scene: NavigationScene): ?ReactElement<any> {
const {
navigationState,
renderScene,
} = this.props;
const {
position,
progress,
scenes,
} = this.state;
return renderScene({
layout: this.state.layout,
navigationState,
position,
progress,
scene,
scenes,
});
}
_renderOverlay(): ?ReactElement<any> {
if (this.props.renderOverlay) {
const {
navigationState,
renderOverlay,
} = this.props;
const {
position,
progress,
scenes,
} = this.state;
const route = navigationState.routes[navigationState.index];
const activeScene = scenes.find(scene => {
return (!scene.isStale && scene.route === route) ?
scene :
undefined;
});
invariant(!!activeScene, 'no active scene found');
return renderOverlay({
layout: this.state.layout,
navigationState,
position,
progress,
scene: activeScene,
scenes,
});
}
return null;
}
_onLayout(event: any): void { _onLayout(event: any): void {
const {height, width} = event.nativeEvent.layout; const {height, width} = event.nativeEvent.layout;
@ -260,10 +190,31 @@ class NavigationTransitioner extends React.Component<any, Props, State> {
} }
this.props.onTransitionEnd && this.props.onTransitionEnd(); this.props.onTransitionEnd && this.props.onTransitionEnd();
} }
_buildTransitionProps(): NavigationTransitionProps {
const {
navigationState,
} = this.props;
const {
layout,
position,
progress,
scenes,
} = this.state;
return {
layout,
navigationState,
position,
progress,
scenes,
};
}
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
scenes: { main: {
flex: 1, flex: 1,
}, },
}); });

View File

@ -45,14 +45,14 @@ export type NavigationScene = {
route: NavigationRoute, route: NavigationRoute,
}; };
export type NavigationSceneRendererProps = { export type NavigationTransitionProps = {
// The layout of the containing view of the scenes. // The layout of the transitioner of the scenes.
layout: NavigationLayout, layout: NavigationLayout,
// The navigation state of the containing view. // The navigation state of the transitioner.
navigationState: NavigationState, navigationState: NavigationState,
// The progressive index of the containing view's navigation state. // The progressive index of the transitioner's navigation state.
position: NavigationAnimatedValue, position: NavigationAnimatedValue,
// The value that represents the progress of the transition when navigation // The value that represents the progress of the transition when navigation
@ -62,11 +62,19 @@ export type NavigationSceneRendererProps = {
// progress.__getAnimatedValue() == 1 : transtion completes. // progress.__getAnimatedValue() == 1 : transtion completes.
progress: NavigationAnimatedValue, progress: NavigationAnimatedValue,
// All the scenes of the transitioner.
scenes: Array<NavigationScene>,
};
export type NavigationSceneRendererProps = {
layout: NavigationLayout,
navigationState: NavigationState,
position: NavigationAnimatedValue,
progress: NavigationAnimatedValue,
scenes: Array<NavigationScene>,
// The scene to render. // The scene to render.
scene: NavigationScene, scene: NavigationScene,
// All the scenes of the containing view's.
scenes: Array<NavigationScene>,
}; };
export type NavigationPanPanHandlers = { export type NavigationPanPanHandlers = {