Pass the current and previous transition props to `render`, `onTransitionStart` and `onTransitionEnd`.
Summary: This shall make it convenient to handle transition changes. Reviewed By: ericvicenti Differential Revision: D3442291 fbshipit-source-id: aee0ffe18ada40ef133484b4a4999f282c66c181
This commit is contained in:
parent
6982f5aa24
commit
c57bac4767
|
@ -19,6 +19,8 @@ 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,
|
||||||
|
@ -33,7 +35,7 @@ type Props = {
|
||||||
navigationState: NavigationState,
|
navigationState: NavigationState,
|
||||||
onTransitionEnd: () => void,
|
onTransitionEnd: () => void,
|
||||||
onTransitionStart: () => void,
|
onTransitionStart: () => void,
|
||||||
render: (props: NavigationTransitionProps) => any,
|
render: (a: NavigationTransitionProps, b: ?NavigationTransitionProps) => any,
|
||||||
style: any,
|
style: any,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,9 +58,10 @@ function isSceneNotStale(scene: NavigationScene): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
class NavigationTransitioner extends React.Component<any, Props, State> {
|
class NavigationTransitioner extends React.Component<any, Props, State> {
|
||||||
|
|
||||||
_onLayout: (event: any) => void;
|
_onLayout: (event: any) => void;
|
||||||
_onTransitionEnd: () => void;
|
_onTransitionEnd: () => void;
|
||||||
|
_prevTransitionProps: ?NavigationTransitionProps;
|
||||||
|
_transitionProps: NavigationTransitionProps;
|
||||||
|
|
||||||
props: Props;
|
props: Props;
|
||||||
state: State;
|
state: State;
|
||||||
|
@ -90,6 +93,9 @@ class NavigationTransitioner extends React.Component<any, Props, State> {
|
||||||
progress: new Animated.Value(1),
|
progress: new Animated.Value(1),
|
||||||
scenes: NavigationScenesReducer([], this.props.navigationState),
|
scenes: NavigationScenesReducer([], this.props.navigationState),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this._prevTransitionProps = null;
|
||||||
|
this._transitionProps = buildTransitionProps(props, this.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount(): void {
|
componentWillMount(): void {
|
||||||
|
@ -108,15 +114,21 @@ class NavigationTransitioner extends React.Component<any, Props, State> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nextState = {
|
||||||
|
...this.state,
|
||||||
|
scenes: nextScenes,
|
||||||
|
};
|
||||||
|
|
||||||
|
this._prevTransitionProps = this._transitionProps;
|
||||||
|
this._transitionProps = buildTransitionProps(nextProps, nextState);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
position,
|
position,
|
||||||
progress,
|
progress,
|
||||||
} = this.state;
|
} = nextState;
|
||||||
|
|
||||||
// update scenes.
|
// update scenes.
|
||||||
this.setState({
|
this.setState(nextState);
|
||||||
scenes: nextScenes,
|
|
||||||
});
|
|
||||||
|
|
||||||
// get the transition spec.
|
// get the transition spec.
|
||||||
const transitionUserSpec = nextProps.configureTransition ?
|
const transitionUserSpec = nextProps.configureTransition ?
|
||||||
|
@ -153,7 +165,10 @@ class NavigationTransitioner extends React.Component<any, Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// play the transition.
|
// play the transition.
|
||||||
nextProps.onTransitionStart && nextProps.onTransitionStart();
|
nextProps.onTransitionStart && nextProps.onTransitionStart(
|
||||||
|
this._transitionProps,
|
||||||
|
this._prevTransitionProps,
|
||||||
|
);
|
||||||
Animated.parallel(animations).start(this._onTransitionEnd);
|
Animated.parallel(animations).start(this._onTransitionEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +177,7 @@ class NavigationTransitioner extends React.Component<any, Props, State> {
|
||||||
<View
|
<View
|
||||||
onLayout={this._onLayout}
|
onLayout={this._onLayout}
|
||||||
style={[styles.main, this.props.style]}>
|
style={[styles.main, this.props.style]}>
|
||||||
{this.props.render(this._buildTransitionProps())}
|
{this.props.render(this._transitionProps, this._prevTransitionProps)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -184,33 +199,55 @@ class NavigationTransitioner extends React.Component<any, Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
_onTransitionEnd(): void {
|
_onTransitionEnd(): void {
|
||||||
|
const prevTransitionProps = this._prevTransitionProps;
|
||||||
|
this._prevTransitionProps = null;
|
||||||
|
|
||||||
const scenes = this.state.scenes.filter(isSceneNotStale);
|
const scenes = this.state.scenes.filter(isSceneNotStale);
|
||||||
if (scenes.length !== this.state.scenes.length) {
|
this.setState({ scenes });
|
||||||
this.setState({ scenes });
|
|
||||||
|
this.props.onTransitionEnd && this.props.onTransitionEnd(
|
||||||
|
this._transitionProps,
|
||||||
|
prevTransitionProps,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildTransitionProps(
|
||||||
|
props: Props,
|
||||||
|
state: State,
|
||||||
|
): NavigationTransitionProps {
|
||||||
|
const {
|
||||||
|
navigationState,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const {
|
||||||
|
layout,
|
||||||
|
position,
|
||||||
|
progress,
|
||||||
|
scenes,
|
||||||
|
} = state;
|
||||||
|
|
||||||
|
return {
|
||||||
|
layout,
|
||||||
|
navigationState,
|
||||||
|
position,
|
||||||
|
progress,
|
||||||
|
scenes,
|
||||||
|
scene: findActiveScene(scenes, navigationState.index),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function findActiveScene(
|
||||||
|
scenes: Array<NavigationScene>,
|
||||||
|
index: number,
|
||||||
|
): NavigationScene {
|
||||||
|
for (let ii = 0, jj = scenes.length; ii < jj; ii++) {
|
||||||
|
const scene = scenes[ii];
|
||||||
|
if (!scene.isStale && scene.index === index) {
|
||||||
|
return scene;
|
||||||
}
|
}
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
invariant(false, 'scenes must have an active scene');
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
|
|
@ -64,19 +64,16 @@ export type NavigationTransitionProps = {
|
||||||
|
|
||||||
// All the scenes of the transitioner.
|
// All the scenes of the transitioner.
|
||||||
scenes: Array<NavigationScene>,
|
scenes: Array<NavigationScene>,
|
||||||
};
|
|
||||||
|
|
||||||
export type NavigationSceneRendererProps = {
|
// The active scene, corresponding to the route at
|
||||||
layout: NavigationLayout,
|
// `navigationState.routes[navigationState.index]`.
|
||||||
navigationState: NavigationState,
|
|
||||||
position: NavigationAnimatedValue,
|
|
||||||
progress: NavigationAnimatedValue,
|
|
||||||
scenes: Array<NavigationScene>,
|
|
||||||
|
|
||||||
// The scene to render.
|
|
||||||
scene: NavigationScene,
|
scene: NavigationScene,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Similar to `NavigationTransitionProps`, except that the prop `scene`
|
||||||
|
// represents the scene for the renderer to render.
|
||||||
|
export type NavigationSceneRendererProps = NavigationTransitionProps;
|
||||||
|
|
||||||
export type NavigationPanPanHandlers = {
|
export type NavigationPanPanHandlers = {
|
||||||
onMoveShouldSetResponder: Function,
|
onMoveShouldSetResponder: Function,
|
||||||
onMoveShouldSetResponderCapture: Function,
|
onMoveShouldSetResponderCapture: Function,
|
||||||
|
|
Loading…
Reference in New Issue