mirror of
https://github.com/status-im/react-native.git
synced 2025-02-27 00:20:31 +00:00
Clean up NavigationAnimatedView
Summary:- Add flow type checks. - Fix code styles. - Improve the logics to update `this.state.scenes`. - Improve the logics to pass the layout. Reviewed By: ericvicenti Differential Revision: D3022107 fb-gh-sync-id: 23f4ed22db797f68bde0ba4f3cdd123701934fc3 shipit-source-id: 23f4ed22db797f68bde0ba4f3cdd123701934fc3
This commit is contained in:
parent
e76fb68141
commit
b5ae8a8ece
@ -21,9 +21,11 @@ const View = require('View');
|
|||||||
import type {
|
import type {
|
||||||
NavigationAnimatedValue,
|
NavigationAnimatedValue,
|
||||||
NavigationAnimationSetter,
|
NavigationAnimationSetter,
|
||||||
|
NavigationLayout,
|
||||||
NavigationParentState,
|
NavigationParentState,
|
||||||
NavigationScene,
|
NavigationScene,
|
||||||
NavigationSceneRenderer,
|
NavigationSceneRenderer,
|
||||||
|
NavigationState,
|
||||||
} from 'NavigationTypeDefinition';
|
} from 'NavigationTypeDefinition';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,71 +104,87 @@ const defaultProps = {
|
|||||||
class NavigationAnimatedView
|
class NavigationAnimatedView
|
||||||
extends React.Component<any, Props, State> {
|
extends React.Component<any, Props, State> {
|
||||||
|
|
||||||
_animatedHeight: Animated.Value;
|
_layout: NavigationLayout;
|
||||||
_animatedWidth: Animated.Value;
|
_onLayout: (event: any) => void;
|
||||||
_lastHeight: number;
|
_onProgressChange: (data: {value: number}) => void;
|
||||||
_lastWidth: number;
|
|
||||||
_positionListener: any;
|
_positionListener: any;
|
||||||
|
|
||||||
props: Props;
|
props: Props;
|
||||||
state: State;
|
state: State;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props: Props, context: any) {
|
||||||
super(props);
|
super(props, context);
|
||||||
this._lastWidth = 0;
|
|
||||||
this._lastHeight = 0;
|
this._layout = {
|
||||||
this._animatedHeight = new Animated.Value(this._lastHeight);
|
initWidth: 0,
|
||||||
this._animatedWidth = new Animated.Value(this._lastWidth);
|
initHeight: 0,
|
||||||
|
width: new Animated.Value(0),
|
||||||
|
height: new Animated.Value(0),
|
||||||
|
};
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
position: new Animated.Value(this.props.navigationState.index),
|
position: new Animated.Value(this.props.navigationState.index),
|
||||||
scenes: [],
|
scenes: this._reduceScenes([], this.props.navigationState),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
componentWillMount() {
|
|
||||||
this.setState({
|
componentWillMount(): void {
|
||||||
scenes: this._reduceScenes(this.state.scenes, this.props.navigationState),
|
this._onLayout = this._onLayout.bind(this);
|
||||||
});
|
this._onProgressChange = this._onProgressChange.bind(this);
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
|
||||||
this._positionListener = this.state.position.addListener(this._onProgressChange.bind(this));
|
componentDidMount(): void {
|
||||||
|
this._positionListener =
|
||||||
|
this.state.position.addListener(this._onProgressChange);
|
||||||
}
|
}
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
|
componentWillReceiveProps(nextProps: Props): void {
|
||||||
if (nextProps.navigationState !== this.props.navigationState) {
|
if (nextProps.navigationState !== this.props.navigationState) {
|
||||||
this.setState({
|
this.setState({
|
||||||
scenes: this._reduceScenes(this.state.scenes, nextProps.navigationState, this.props.navigationState),
|
scenes: this._reduceScenes(
|
||||||
|
this.state.scenes,
|
||||||
|
nextProps.navigationState,
|
||||||
|
this.props.navigationState
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentDidUpdate(lastProps) {
|
|
||||||
if (lastProps.navigationState.index !== this.props.navigationState.index && this.props.setTiming) {
|
componentDidUpdate(lastProps: Props): void {
|
||||||
this.props.setTiming(this.state.position, this.props.navigationState, lastProps.navigationState);
|
if (lastProps.navigationState.index !== this.props.navigationState.index) {
|
||||||
|
this.props.setTiming(
|
||||||
|
this.state.position,
|
||||||
|
this.props.navigationState,
|
||||||
|
lastProps.navigationState
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentWillUnmount() {
|
|
||||||
if (this._positionListener) {
|
componentWillUnmount(): void {
|
||||||
this.state.position.removeListener(this._positionListener);
|
this.state.position.removeListener(this._positionListener);
|
||||||
this._positionListener = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onProgressChange(data: Object): void {
|
_onProgressChange(data: Object): void {
|
||||||
if (Math.abs(data.value - this.props.navigationState.index) > Number.EPSILON) {
|
const delta = Math.abs(data.value - this.props.navigationState.index);
|
||||||
|
if (delta > Number.EPSILON) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.state.scenes.forEach((scene, index) => {
|
|
||||||
if (scene.isStale) {
|
const scenes = this.state.scenes.filter(scene => {
|
||||||
const scenes = this.state.scenes.slice();
|
return !scene.isStale;
|
||||||
scenes.splice(index, 1);
|
|
||||||
this.setState({ scenes, });
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (scenes.length !== this.state.scenes.length) {
|
||||||
|
this.setState({ scenes });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_reduceScenes(
|
_reduceScenes(
|
||||||
scenes: Array<NavigationScene>,
|
scenes: Array<NavigationScene>,
|
||||||
nextState: NavigationParentState,
|
nextState: NavigationParentState,
|
||||||
lastState: ?NavigationParentState
|
lastState: ?NavigationParentState
|
||||||
): Array<NavigationScene> {
|
): Array<NavigationScene> {
|
||||||
let nextScenes = nextState.children.map((child, index) => {
|
const nextScenes = nextState.children.map((child, index) => {
|
||||||
return {
|
return {
|
||||||
index,
|
index,
|
||||||
isStale: false,
|
isStale: false,
|
||||||
@ -175,8 +193,11 @@ class NavigationAnimatedView
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (lastState) {
|
if (lastState) {
|
||||||
lastState.children.forEach((child, index) => {
|
lastState.children.forEach((child: NavigationState, index: number) => {
|
||||||
if (!NavigationStateUtils.get(nextState, child.key) && index !== nextState.index) {
|
if (
|
||||||
|
!NavigationStateUtils.get(nextState, child.key) &&
|
||||||
|
index !== nextState.index
|
||||||
|
) {
|
||||||
nextScenes.push({
|
nextScenes.push({
|
||||||
index,
|
index,
|
||||||
isStale: true,
|
isStale: true,
|
||||||
@ -186,38 +207,21 @@ class NavigationAnimatedView
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
nextScenes = nextScenes.sort(compareScenes);
|
return nextScenes.sort(compareScenes);
|
||||||
|
|
||||||
return nextScenes;
|
|
||||||
}
|
}
|
||||||
render() {
|
|
||||||
|
render(): ReactElement {
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
onLayout={(e) => {
|
onLayout={this._onLayout}
|
||||||
const {height, width} = e.nativeEvent.layout;
|
|
||||||
this._animatedHeight &&
|
|
||||||
this._animatedHeight.setValue(height);
|
|
||||||
this._animatedWidth &&
|
|
||||||
this._animatedWidth.setValue(width);
|
|
||||||
this._lastHeight = height;
|
|
||||||
this._lastWidth = width;
|
|
||||||
}}
|
|
||||||
style={this.props.style}>
|
style={this.props.style}>
|
||||||
{this.state.scenes.map(this._renderScene, this)}
|
{this.state.scenes.map(this._renderScene, this)}
|
||||||
{this._renderOverlay()}
|
{this._renderOverlay()}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_getLayout() {
|
|
||||||
return {
|
|
||||||
height: this._animatedHeight,
|
|
||||||
width: this._animatedWidth,
|
|
||||||
initWidth: this._lastWidth,
|
|
||||||
initHeight: this._lastHeight,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_renderScene(scene: NavigationScene) {
|
_renderScene(scene: NavigationScene): ?ReactElement {
|
||||||
const {
|
const {
|
||||||
navigationState,
|
navigationState,
|
||||||
onNavigate,
|
onNavigate,
|
||||||
@ -230,7 +234,7 @@ class NavigationAnimatedView
|
|||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
return renderScene({
|
return renderScene({
|
||||||
layout: this._getLayout(),
|
layout: this._layout,
|
||||||
navigationState,
|
navigationState,
|
||||||
onNavigate,
|
onNavigate,
|
||||||
position,
|
position,
|
||||||
@ -239,7 +243,7 @@ class NavigationAnimatedView
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderOverlay() {
|
_renderOverlay(): ?ReactElement {
|
||||||
if (this.props.renderOverlay) {
|
if (this.props.renderOverlay) {
|
||||||
const {
|
const {
|
||||||
navigationState,
|
navigationState,
|
||||||
@ -253,7 +257,7 @@ class NavigationAnimatedView
|
|||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
return renderOverlay({
|
return renderOverlay({
|
||||||
layout: this._getLayout(),
|
layout: this._layout,
|
||||||
navigationState,
|
navigationState,
|
||||||
onNavigate,
|
onNavigate,
|
||||||
position,
|
position,
|
||||||
@ -263,6 +267,21 @@ class NavigationAnimatedView
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigationAnimatedView.propTypes = propTypes;
|
NavigationAnimatedView.propTypes = propTypes;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user