问题
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