React Native two drawers on one screen

耗尽温柔 提交于 2020-05-28 05:31:46

问题


I have an app that needs to be able to use two drawer navigators, one on the left and on on the right side of the header.

I am at the point where I can get both drawers to open with the slide gesture, however I need to be able to open it programmatically. I have found the navigation.openDrawer() function only works with one of the drawers and not the other because it is only able to use one of the navigation props (whichever comes first) from my drawer navigators.

Below are my rendering functions:

const LeftStack = createStackNavigator(
  {
    LeftDrawerStack
  },
  {
    navigationOptions: ({navigation}) => ({
      headerLeft: (
        <TouchableOpacity onPress={() => navigation.openDrawer()}>
          <Icon style={{marginLeft: 10}} name='menu'/>
        </TouchableOpacity>
      )
    })
  }
);

const RightStack = createStackNavigator(
  {
    RightDrawerStack
  },
  {
    navigationOptions: ({navigation}) => ({
      headerRight: (
        <TouchableOpacity onPress={() => navigation.openDrawer()}>
          <Icon style={{marginRight: 10}} name='ios-bulb'/>
        </TouchableOpacity>
      )
    })
  }
);

export const RouteStack = createStackNavigator(
  {
    screen: LoginScreen,
    navigationOptions: ({navigation}) => ({
      header: null
    }),
    LeftStack,
    RightStack
  }
);

and here are my drawer routes:

export const LeftDrawerStack = createDrawerNavigator(
  {
    Dashboard: {
      screen: DashboardScreen
    },
    History: {
      screen: HistoryScreen
    },
    Privacy: {
      screen: PrivacyPolicyScreen
    },
    TermsAndConditions: {
      screen: TermsAndConditionsScreen
    }
  }, {
    initialRouteName: 'Dashboard',
    contentComponent: LeftDrawerScreen
  }
);

export const RightDrawerStack = createDrawerNavigator(
  {
    LeftDrawerStack,
    Settings: {
      screen: SettingsScreen
    }
  }, {
    drawerPosition: 'right',
    contentComponent: RightDrawerScreen
  }
);

Here is a picture of what I have the navigation looking like so far, however both of the hamburger menus are opening up the same menu on the right instead of one menu on their respective sides.

I may be missing some parts but I will be sure to post more info if I forgot any!


回答1:


I was able to do this with the following setup (try to make changes to your structure to be like this):

const LeftDrawer = createDrawerNavigator(
{
    LeftDrawer: MyStackNavigator,
},
    {
        getCustomActionCreators: (route, stateKey) => { return { toggleLeftDrawer: () => DrawerActions.toggleDrawer({ key: stateKey }) }; },
        drawerPosition: 'left',
        contentComponent: MyLeftDrawer
    }
);

const RightDrawer = createDrawerNavigator(
{
    Drawer: LeftDrawer,
},
    {
        getCustomActionCreators: (route, stateKey) => { return { toggleRightDrawer: () => DrawerActions.toggleDrawer({ key: stateKey }) }; },
        drawerPosition: 'right',
        contentComponent: MyRightDrawer
    }
);

export const RootNavigator = createStackNavigator(
{
    Login: Login,
    Home: RightDrawer
},
    {
        initialRouteName: 'Login',
        navigationOptions: { header: null, gesturesEnabled: false }
    }
);

The key is getCustomActionCreators. It allows you to call the function from any screen in MyStackNavigator like this: this.props.navigation.toggleLeftDrawer();.




回答2:


This is solution I do

Step 1: Create two drawer navigation and nest them together

Step 2: Store first drawer navigation in other place (Singleton)

// Drawer 1
import ContentLeftMenu from '@components/ContentLeftMenu';
import { createDrawerNavigator } from '@react-navigation/drawer';
import * as React from 'react';
import DrawerCart from './DrawerCart';
import { setNavigationDrawerHome } from './RootNavigation';
import { isTablet } from 'react-native-device-info';
import MainStack from './MainStack';

const Drawer = createDrawerNavigator();

export default function DrawerHome() {
  return (
    <Drawer.Navigator
      initialRouteName="DrawerCart"
      drawerContent={() => <ContentLeftMenu />}
      screenOptions={({ navigation, route }) => {
        setNavigationDrawerHome(navigation)
      }}
    >
      <Drawer.Screen name="DrawerCart" component={isTablet ? DrawerCart : MainStack} />
    </Drawer.Navigator>
  );
}
// Drawer 2
import CartScreen from '@features/cart/CartScreen';
import { createDrawerNavigator } from '@react-navigation/drawer';
import * as React from 'react';
import MainStack from './MainStack';

const Drawer = createDrawerNavigator();

export default function DrawerCart(props) {
  return (
    <Drawer.Navigator
      initialRouteName="MainStackCart"
      drawerContent={() => <CartScreen />}
      drawerPosition='right'
    >
      <Drawer.Screen name="MainStackCart" component={MainStack} />
    </Drawer.Navigator>
  );
}
// set navigation of drawer 1 with navigationDrawerHome
let navigationDrawerHome = null

export const setNavigationDrawerHome = (navigation) => {
  navigationDrawerHome = navigation
}

export const getNavigationDrawerHome = () => {
  return navigationDrawerHome
}

And when I use in Mainstack I when open Drawer 1 in left I use navigationDrawerHome, with drawer 2 just use navigation props

const Stack = createStackNavigator();

function MainStack() {
  const navigationDrawerHome = getNavigationDrawerHome()
  return (
    <Stack.Navigator
      screenOptions={({ navigation, route }) => ({
        headerLeft: () => <HeaderLeft />,
        headerTitleAlign: 'center',
      })}>
      <Stack.Screen
        name="home_user_tab"
        component={HomeUserTabs}
        options={({ navigation, route }) => ({
          headerLeft: () => {
            return (
              <ButtonIcon
                onPress={() => navigationDrawerHome.openDrawer()}
                style={styles.buttonLeft}
                icon={images.ic_left_menu}
              />
            )
          },
          headerTitle: () => <LogoHeader />,
          headerRight: () => (<HeaderCardSearch
            navigation={navigation}
          />),
          // header: null
        })}
      />
    </Stack.Navigator>
  );
}
const HeaderCardSearch = (props) => {
  const { navigation } = props;
  return (
    <View style={styles.headerRight}>
      <ButtonIcon
        onPress={() => navigation.openDrawer()}
        style={styles.buttonCart}
        icon={images.ic_cart}
      />
      <ButtonIcon
        onPress={() => navigate('search')}
        style={styles.buttonSearch}
        icon={images.ic_search}
      />
    </View>
  )
};



回答3:


I managed to programmatically open both drawers this way:

// Opens left drawer
this.props.navigation.openDrawer();

// Opens right drawer
this.props.navigation.dangerouslyGetParent().dangerouslyGetParent().openDrawer();

And my navigation container looks like this:

static container = (): NavigationContainer => createDrawerNavigator({
    right: createDrawerNavigator({
        left: DeviceControlContainer
    }, {
        contentComponent: HistoryDrawerContainer,
        overlayColor: drawerOverlayColor()
    })
}, {
    drawerPosition: 'right',
    overlayColor: drawerOverlayColor(),
    navigationOptions: DeviceControlScreen.navigationOptions,
    contentComponent: DeviceControlDrawer
});


来源:https://stackoverflow.com/questions/51391287/react-native-two-drawers-on-one-screen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!