Files
react-navigation/createNativeStackNavigator.js
2019-09-09 10:31:15 +02:00

191 lines
5.3 KiB
JavaScript

import React from 'react';
import { StyleSheet, Text } from 'react-native';
import {
StackRouter,
SceneView,
StackActions,
NavigationActions,
createNavigator,
} from '@react-navigation/core';
import { createKeyboardAwareNavigator } from '@react-navigation/native';
import { ScenesReducer, HeaderBackButton } from 'react-navigation-stack';
import {
ScreenStack,
Screen,
ScreenStackHeaderConfig,
ScreenStackHeaderLeftView,
ScreenStackHeaderRightView,
ScreenStackHeaderTitleView,
} from 'react-native-screens';
class StackView extends React.Component {
_removeScene = scene => {
const { navigation } = this.props;
navigation.dispatch(
NavigationActions.back({
key: scene.route.key,
immediate: true,
})
);
navigation.dispatch(StackActions.completeTransition());
};
_renderHeaderConfig = (scene, scenes) => {
const { navigationConfig } = this.props;
const { options } = scene.descriptor;
const { headerMode } = navigationConfig;
const {
title,
headerStyle,
headerTitleStyle,
headerBackTitleStyle,
headerBackTitle,
headerTintColor,
gestureEnabled,
largeTitle,
translucent,
} = options;
const headerOptions = {
translucent: translucent === undefined ? false : translucent,
title,
titleFontFamily: headerTitleStyle && headerTitleStyle.fontFamily,
titleColor: headerTintColor,
titleFontSize: headerTitleStyle && headerTitleStyle.fontSize,
backTitle: headerBackTitle,
backTitleFontFamily:
headerBackTitleStyle && headerBackTitleStyle.fontFamily,
backTitleFontSize: headerBackTitleStyle && headerBackTitleStyle.fontSize,
color: headerTintColor,
gestureEnabled: gestureEnabled === undefined ? true : gestureEnabled,
largeTitle,
};
const hasHeader = headerMode !== 'none' && options.header !== null;
if (!hasHeader) {
return <ScreenStackHeaderConfig {...headerOptions} hidden />;
}
if (headerStyle !== undefined) {
headerOptions.backgroundColor = headerStyle.backgroundColor;
}
const children = [];
if (options.headerLeft !== undefined) {
children.push(
<ScreenStackHeaderLeftView key="left">
{options.headerLeft({ scene })}
</ScreenStackHeaderLeftView>
);
} else if (options.headerBackImage !== undefined) {
const goBack = () => {
// Go back on next tick because button ripple effect needs to happen on Android
requestAnimationFrame(() => {
scene.descriptor.navigation.goBack(scene.descriptor.key);
});
};
children.push(
<ScreenStackHeaderLeftView key="left">
<HeaderBackButton
onPress={goBack}
pressColorAndroid={options.headerPressColorAndroid}
tintColor={options.headerTintColor}
backImage={options.headerBackImage}
title={options.backButtonTitle}
truncatedTitle={options.truncatedBackButtonTitle}
backTitleVisible={this.props.backTitleVisible}
titleStyle={options.headerBackTitleStyle}
layoutPreset={this.props.layoutPreset}
scene={scene}
/>
</ScreenStackHeaderLeftView>
);
}
if (options.headerTitle) {
children.push(
<ScreenStackHeaderTitleView key="title">
{options.headerTitle({ scene })}
</ScreenStackHeaderTitleView>
);
}
if (options.headerRight) {
children.push(
<ScreenStackHeaderRightView key="right">
{options.headerRight({ scene })}
</ScreenStackHeaderRightView>
);
}
if (children.length > 0) {
headerOptions.children = children;
}
return <ScreenStackHeaderConfig {...headerOptions} />;
};
_renderScene = (scene, scenes) => {
const { navigation, getComponent } = scene.descriptor;
const { mode, transparentCard } = this.props.navigationConfig;
const SceneComponent = getComponent();
let stackPresentation = 'push';
if (mode === 'modal') {
stackPresentation = transparentCard ? 'transparentModal' : 'modal';
}
const { screenProps } = this.props;
return (
<Screen
key={`screen_${scene.key}`}
style={StyleSheet.absoluteFill}
stackPresentation={stackPresentation}
onDismissed={() => this._removeScene(scene)}>
{this._renderHeaderConfig(scene, scenes)}
<SceneView
screenProps={screenProps}
navigation={navigation}
component={SceneComponent}
/>
</Screen>
);
};
render() {
const scenes = ScenesReducer(
[],
this.props.navigation.state,
null,
this.props.descriptors
);
return (
<ScreenStack style={styles.scenes}>
{scenes.map(scene => this._renderScene(scene, scenes))}
</ScreenStack>
);
}
}
const styles = StyleSheet.create({
scenes: { flex: 1 },
});
function createStackNavigator(routeConfigMap, stackConfig = {}) {
const router = StackRouter(routeConfigMap, stackConfig);
// Create a navigator with StackView as the view
let Navigator = createNavigator(StackView, router, stackConfig);
// if (!stackConfig.disableKeyboardHandling) {
// Navigator = createKeyboardAwareNavigator(Navigator, stackConfig);
// }
return Navigator;
}
export default createStackNavigator;