• Home
  • React Native
  • StackNavigator wewnątrz DrawerNavigator – połączenie dwóch nawigatorów w jednej aplikacji

StackNavigator wewnątrz DrawerNavigator – połączenie dwóch nawigatorów w jednej aplikacji


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ć.

Jeśli nie wiesz, jak używać nawigacji w React Native, zajrzyj do moich poprzednich wpisów: StackNavigator example i DrawerNaviagator example
 

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:

Nested StackNavigator inside DrawerNavigator - React Native // StackNavigator wewnątrz DrawerNavigator - połączenie dwóch nawigatorów w jednej aplikacji

Joanna

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *