Często spotyka się aplikacje napisane w React Native, które używają dwóch lub więcej nawigatorów na raz. Sama miałam problem z połączeniem stack nawigatora i drawer navigatora, na szczęście udało mi się połączyć je tak, aby działały poprawnie i teraz mogę się tą wiedzą podzielić.
Zacznijmy od początku, czyli od komponentu App.js. W naszym przypadku będzie on bardzo prosty, zwraca bowiem tylko jeden komponent, którym jest DrawerNavigator.
App.js
import React, {Component} from 'react';
import DrawerNavigator from './components/DrawerNavigator';
export default class App extends Component {
render() {
return (
<DrawerNavigator />
);
}
}
W drawer navigatorze tworzymy cztery ekrany – jeden główny, który zawierał będzie StackNavigator i trzy inne, które zawierać będą pozostałe dane.
DrawerNavigator.js
import React, {Component} from 'react';
import { createDrawerNavigator, createAppContainer } from 'react-navigation';
import Screen1 from './Screen1';
import Screen2 from './Screen2';
import Screen3 from './Screen3';
import ContentComponent from './ContentComponent';
import {Dimensions} from 'react-native';
import StackNavigator from './StackNavigator';
const MyDrawerNavigator = createDrawerNavigator({
Home: {screen: StackNavigator},
Screen1: {screen: Screen1},
Screen2: {screen: Screen2},
Screen3: {screen: Screen3},
},
{
initialRouteName: 'Home',
drawerWidth: Dimensions.get('window').width,
drawerPosition: 'left',
}
);
const AppContainer = createAppContainer(MyDrawerNavigator);
export default class DrawerNavigator extends Component {
render() {
return <AppContainer />;
}
}
Jak widać jako ekran główny (initialRouteName) w drawer nawigatorze ustawiliśmy StackNavigator, zajmijmy się więc tym komponentem
StackNavigator.js
import React, {Component} from 'react';
import { createStackNavigator, createAppContainer, DrawerActions } from 'react-navigation';
import HomeScreen from './HomeScreen';
import Screen4 from './Screen4';
import Screen5 from './Screen5';
const MyStackNavigator = createStackNavigator(
{
Home: {screen: HomeScreen},
Screen4: Screen4,
Screen5: Screen5,
},
{
initialRouteName: 'Home',
defaultNavigationOptions: {
headerStyle: { height: 55, backgroundColor: 'orange' },
//headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold', color: '#fff' },
},
transitionConfig: () => ({
transitionSpec: {
duration: 500,
},
screenInterpolator: sceneProps => {
const { position, layout, scene } = sceneProps;
const index = scene.index;
const width = layout.initWidth;
const slideFromRight = {
opacity: position.interpolate({
inputRange: [ index, index + 1],
outputRange: [1, 1],
}),
transform: [{
translateX: position.interpolate({
inputRange: [index - 1, index, index + 1],
outputRange: [width, 0, -20],
})
}] };
return slideFromRight;
},
}),
}
);
const AppContainer = createAppContainer(MyStackNavigator);
export default class StackNavigator extends Component {
render() {
return <AppContainer screenProps={{ openDraw: () => this.props.navigation.dispatch(DrawerActions.openDrawer()) }} />;
}
}
Tutaj już sprawa przedstawia się nieco inaczej: jako ekran główny ustawiliśmy HomeScreen i z jego poziomu (konkretnie z nagłówka) chcemy otworzyć drawer nawigatora. Jednak właściwość navigation w stack nawigatorze nie posiada opcji otwierania drawer nawigatora. Dlatego właśnie musimy tę opcję przekazać z drawer nawigatora do stack nawigatora, a z niego do komponentu głównego HomeScreen. Zrobimy to przekazując ją za pomocją screenProps – jako dodatkową właściwość.
Teraz w komponencie HomeScreen możemy odczytać właściwość otwierającą drawer nawigator i umieścić ją w nagłówku uzywając static navigationOptions.
HomeScreen.js
import React, {Component} from 'react';
import {StyleSheet, Text, View, TouchableHighlight, Button} from 'react-native';
export default class HomeScreen extends Component {
static navigationOptions = ({ screenProps }) => ({
title: 'Home',
headerLeft: (
<Button onPress={() => screenProps.openDraw() }
title="OPEN"
color="red"
/>
),
})
render() {
return (
<View style={styles.view}>
<Text style={styles.text}>This is homescreen</Text>
<TouchableHighlight onPress={() => this.props.navigation.navigate('Screen4')} style={styles.touchableHighlight} underlayColor={'#f1f1f1'}>
<Text style={styles.text}>Go to Screen 2</Text>
</TouchableHighlight>
</View>
);
}
}
Style dodacie sobie sami 😉
Efekt prezentuje się następująco: