在一个屏幕上对Native两个抽屉进行反应

时间:2018-07-17 22:59:14

标签: javascript android ios react-native react-navigation

我有一个应用程序,它需要能够使用两个抽屉式导航器,一个在标题的左侧和右侧。

我现在可以用滑动手势打开两个抽屉,但是我需要能够以编程方式打开它。我发现navigation.openDrawer()函数仅适用于其中一个抽屉,而不适用于另一个,因为它只能使用我的抽屉导航器中的一个导航道具(以先到者为准)。

以下是我的渲染功能:

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
  }
);

这是我的抽屉路线:

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
  }
);

这是到目前为止我的导航外观的图片,但是两个汉堡菜单都在右侧打开相同的菜单,而不是在各自侧面打开一个菜单。

layout picture

我可能会缺少某些部分,但是如果我忘记了任何信息,我一定会发布更多信息!

4 个答案:

答案 0 :(得分:1)

我能够通过以下设置来做到这一点(尝试像这样对您的结构进行更改):

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 }
    }
);

键是getCustomActionCreators。它允许您从MyStackNavigator中的任何屏幕调用函数,如下所示:this.props.navigation.toggleLeftDrawer();

答案 1 :(得分:1)

这是我的解决方法

第1步:创建两个抽屉式导航并将其嵌套在一起<​​/ p>

第2步:将第一个抽屉式导航存储在其他位置(单人)

// 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
}

当我在Mainstack中使用时,当我打开左侧的Drawer 1时,我使用的是NavigationDrawerHome,而抽屉2则使用导航道具

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>
  )
};

答案 2 :(得分:0)

我设法通过编程方式打开了两个抽屉:

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

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

我的导航容器如下所示:

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

答案 3 :(得分:0)

得益于Anh Devit解决方案的启发,这是我的。我在没有Stack Navigator的情况下在应用程序中使用了标题栏,因此必须走些许不同的路线。

对于我的RootNavigator,我将标题放在第一个抽屉上方。我使用useState,所以当我将导航对象作为道具传递时,AppHeader可以在初始化抽屉后正确地重新渲染。

import React, { useState } from "react";
import { NavigationContainer } from "@react-navigation/native";

import LeftDrawer from "./LeftDrawer";
import AppHeader from "./AppHeader";

const RootNavigator = () => {
  const [navigationLeftDrawer, setNavigationLeftDrawer] = useState(null);
  const [navigationRightDrawer, setNavigationRightDrawer] = useState(null);

  return (
    <NavigationContainer>
      <AppHeader
        navigationLeftDrawer={navigationLeftDrawer}
        navigationRightDrawer={navigationRightDrawer}
      />
      <LeftDrawer
        navigationLeftDrawer={(navigation) =>
          setNavigationLeftDrawer(navigation)
        }
        navigationRightDrawer={(navigation) =>
          setNavigationRightDrawer(navigation)
        }
      />
    </NavigationContainer>
  );
};

export default RootNavigator;

在这里,我正在创建LeftDrawer,其中将嵌套RightDrawer。注意在抽屉启动时设置navigationLeftDrawer。另外,navigationRightDrawer必须作为参数而不是道具来传递。

import React, { useContext } from "react";
import {
  createDrawerNavigator,
  DrawerContentScrollView,
  DrawerItem,
} from "@react-navigation/drawer";

import RightDrawer from "./RightDrawer";

const LeftDrawer = ({ navigationLeftDrawer, navigationRightDrawer }) => {
  const Drawer = createDrawerNavigator();

  return (
    <Drawer.Navigator
      screenOptions={({ navigation }) => {
        navigationLeftDrawer(navigation);
      }}
      drawerContent={(props) => {
        const { navigate } = props.navigation;
        return (<RightDrawerItems />)
        );
      }}
    >
      <Drawer.Screen
        name="AccountDrawer"
        component={RightDrawer}
        initialParams={{ navigationRightDrawer }}
      />
    </Drawer.Navigator>
  );

export default LeftDrawer;

RightDrawer中的情况类似,将navigationRightDrawer与正确的导航对象向上传递。

import React from "react";

const RightDrawer = ({ route }) => {
  const Drawer = createDrawerNavigator();
  const { navigationRightDrawer } = route.params;

  return (
    <Drawer.Navigator
      drawerPosition="right"
      screenOptions={({ navigation }) => {
        navigationRightDrawer(navigation);
      }}
      drawerContent={(props) => {
        const { navigate } = props.navigation;
        return ( <RightDrawerItems />);
      }}
    >
      {userAuth ? (
        <>
          <Drawer.Screen name={routes.dashboard} component={DashboardScreen} />
        </>
      ) : (
        <Drawer.Screen name={routes.home} component={HomeStack} />
      )}
      <Drawer.Screen name={routes.about} component={AboutScreen} />
      <Drawer.Screen name={routes.language} component={LanguageScreen} />
    </Drawer.Navigator>
  );
};

export default RightDrawer;

最后,AppHeader

import React, { useContext } from "react";

const AppHeader = ({ navigationRightDrawer, navigationLeftDrawer }) => {

  if (navigationRightDrawer == null || navigationLeftDrawer == null)
    return null;

  return (
    <View style={styles.container}>
      <Icon
        name="menu"
        color={colors.white}
        onPress={() => {
          navigationRightDrawer.closeDrawer();
          navigationLeftDrawer.toggleDrawer();
        }}
      />
      {userAuth ? (
        <TouchableWithoutFeedback
          onPress={() => {
            navigationLeftDrawer.closeDrawer();
            navigationRightDrawer.toggleDrawer();
          }}
        >
          <Image
            style={styles.image}
            source={{ uri: userProfile.profilePicture }}
          />
        </TouchableWithoutFeedback>
      ) : (
        <Icon
          name="person"
          color={colors.secondary}
          onPress={() => navigationLeftDrawer.navigate(routes.login)}
        />
      )}
    </View>
  );
};

export default AppHeader;