React Navigation 5隐藏抽屉项

时间:2020-02-25 13:15:23

标签: react-native react-navigation react-navigation-drawer react-navigation-v5

我试图隐藏在抽屉式导航器中按我的一条路线的功能,因为它是另一个导航器,也是应用程序中的默认位置。我希望将抽屉仅用于导航到不适合其他地方用户流的无关路线。在React Navigation 5之前,我只需设置drawerLabel: () => null就可以实现这一点。但是,现在通过更改,我无法弄清楚如何以相同的方式隐藏它。

以下是我当前的导航代码:

const DrawerNavigator = () => {
    const dispatch = useDispatch();
    return (
    <MainDrawerNavigator.Navigator 
        drawerContent={props => customDrawerContent(props, dispatch)}
        drawerStyle={drawerStyle}
    >
        <MainDrawerNavigator.Screen 
            name="DrawerNav"
            component={MainTabNavigator}
            options={{
                drawerLabel: () => null,
                title: null,
                drawerIcon: () => null
            }}
        />

        <MainDrawerNavigator.Screen
            name="FAQNav"
            component={FAQStackNavigator}
            options={
                { 
                    drawerLabel: "FAQ", 
                    drawerIcon: ({tintColor}) => <EvilIcons name={'question'} size={30} color={tintColor} />
                }
            }
        />
    </MainDrawerNavigator.Navigator>
    )
}

const customDrawerContent = (props, dispatch) => {
    console.log(props.descriptors)
    return (
        <View style={{flex: 1}}>
            <View style={{height: '90%'}}>

                <DrawerContentScrollView {...props}>
                        <View style={styles.logoContainer}>
                            <Image 
                                style={styles.image} 
                                fadeDuration={0} 
                                resizeMode={'contain'} 
                                source={require('../assets/images/spikeball-logo-horizontal.png')} 
                            />
                        </View>

                        <TouchableOpacity style={styles.contactUsContainer} onPress={() => { Linking.openURL('https://spikeball.com/')}}>
                            <AntDesign style={styles.iconStyle} name={'shoppingcart'} size={25} color={'black'} />

                            <Text style={styles.drawerText}>Shop</Text>                    
                        </TouchableOpacity>

                        <TouchableOpacity style={styles.contactUsContainer} onPress={() => { Linking.openURL('https://support.spikeball.com/')}}>
                            <AntDesign style={styles.iconStyle} name={'contacts'} size={25} color={'black'} />

                            <Text style={styles.drawerText}>Contact Us</Text>                    
                        </TouchableOpacity>

                        <DrawerItemList 
                            {...props}
                        />

                </DrawerContentScrollView>
            </View>

            <TouchableOpacity 
                style={styles.logoutContainer} 
                onPress={() => { 
                    dispatch(authActions.logout());
                }}>
                    <Text style={styles.logoutText}>SIGN OUT</Text>                    
            </TouchableOpacity>
        </View>
    )
}

链接到显示不良输出的图像。基本上,我希望从焦点栏上隐藏蓝色焦点和整个导航项。 UNDESIRED Output

7 个答案:

答案 0 :(得分:10)

最佳解决方案是先过滤道具,然后再将其传递到 DrawerItemList 。这仅适用于反应导航5

INTERACTION

}

答案 1 :(得分:6)

解决了以下问题

import React from 'react';
import { SafeAreaView, View, Text, StyleSheet, Image, Linking } from 'react-native';
import { EvilIcons, AntDesign } from '@expo/vector-icons';
import { useDispatch } from 'react-redux';
import { createDrawerNavigator, DrawerContentScrollView, DrawerItemList, DrawerItem } from '@react-navigation/drawer';

import MainTabNavigator from './MainTabNavigator';
import FAQStackNavigator from './FAQStackNavigator';
import { TouchableOpacity } from 'react-native-gesture-handler';
import * as authActions from '../store/actions/auth';
import { moderateScale } from '../utils/fontScale';

const MainDrawerNavigator = createDrawerNavigator();

const DrawerNavigator = () => {
    const dispatch = useDispatch();
    return (
    <MainDrawerNavigator.Navigator 
        drawerContent={props => customDrawerContent(props, dispatch)}
        drawerStyle={drawerStyle}
    >
        <MainDrawerNavigator.Screen 
            name="DrawerNav"
            component={MainTabNavigator}
            options={{
                drawerLabel: () => null,
                title: null,
                drawerIcon: () => null
            }}
        />

        <MainDrawerNavigator.Screen
            name="FAQNav"
            component={FAQStackNavigator}
            options={
                { 
                    drawerLabel: "FAQ", 
                    drawerIcon: ({tintColor}) => <EvilIcons name={'question'} size={30} color={tintColor} />
                }
            }
        />
    </MainDrawerNavigator.Navigator>
    )
}

const customDrawerContent = (props, dispatch) => {
    return (
        <View style={{flex: 1}}>
            <View style={{height: '90%'}}>

                <DrawerContentScrollView {...props}>
                        <View style={styles.logoContainer}>
                            <Image 
                                style={styles.image} 
                                fadeDuration={0} 
                                resizeMode={'contain'} 
                                source={require('...')} 
                            />
                        </View>

                        <TouchableOpacity style={styles.contactUsContainer} onPress={() => { Linking.openURL('...')}}>
                            <AntDesign style={styles.iconStyle} name={'shoppingcart'} size={25} color={'black'} />

                            <Text style={styles.drawerText}>Shop</Text>                    
                        </TouchableOpacity>

                        <TouchableOpacity style={styles.contactUsContainer} onPress={() => { Linking.openURL('...')}}>
                            <AntDesign style={styles.iconStyle} name={'contacts'} size={25} color={'black'} />

                            <Text style={styles.drawerText}>Contact Us</Text>                    
                        </TouchableOpacity>

                        {/* Tried just disabling using DrawerItemList but wasn't working so made
                        complete custom drawer component and navigate properly using props.navigation.navigate */}
                        {/* <DrawerItemList 
                            {...props}
                        /> */}

                        <TouchableOpacity 
                            style={styles.contactUsContainer} 
                            onPress={() => { console.log(props.navigation.navigate('FAQNav'))}}
                        >
                            <EvilIcons name={'question'} size={30} color={'black'} />
                            <Text style={styles.drawerText}>FAQ</Text>                    
                        </TouchableOpacity>
                </DrawerContentScrollView>
            </View>

            <TouchableOpacity 
                style={styles.logoutContainer} 
                onPress={() => { 
                    dispatch(authActions.logout());
                }}>
                    <Text style={styles.logoutText}>SIGN OUT</Text>                    
            </TouchableOpacity>
        </View>
    )
}

const drawerStyle = {
    activeTintColor: 'black',
    inactiveTintColor: 'black',
    labelStyle: {
        fontFamily: 'montserrat',
        marginVertical: 16,
        marginHorizontal: 0,
    },
    iconContainerStyle: {
        justifyContent: 'center',
        alignItems: 'center',
    },
    itemStyle: {

    }
}

const styles = StyleSheet.create({
    safeArea: {
        flex: 1,
        paddingTop: Platform.OS === 'android' ? 25 : 0
    },
    container: {
        flex: 1,  
    },
    logoContainer: {
        width: '100%',
        height: moderateScale(50),
        alignItems: 'center',
        justifyContent: 'center',
        marginBottom: 5,
        padding: 5,
    },
    image: {
        resizeMode: 'contain',
        width: '80%',
        height: '100%',
    },
    contactUsContainer: {
        flexDirection: 'row',
        width: '100%',
        height: 50,
        alignItems: 'center',
        paddingLeft: 15
    },
    logoutContainer: {
        flexDirection: 'row',
        width: '100%',
        height: 50,
        alignItems: 'flex-end',
        justifyContent: 'center',
    },
    drawerText: {
        fontFamily: 'montserrat',
        marginLeft: 16,
    },
    logoutText: {
        fontFamily: 'montserrat',
        color: '#b23b3b'
    }
});

export default DrawerNavigator;

答案 2 :(得分:0)

对我来说,您最好创建https://reactnavigation.org/docs/nesting-navigators/#navigator-specific-methods-are-available-in-the-navigators-nested-inside中记录的带有堆栈和抽屉屏幕的嵌套导航器,而不是隐藏抽屉项目。

答案 3 :(得分:0)

React导航解决方案5

我最终使用了以下代码-

drawerContent={props => customDrawerContent(props, dispatch)}

customDrawerContent的代码-

{state.routes.map((route, i) => {
          if(route.name === 'App') return;
          const focused = i === state.index;
          const { title, drawerLabel, drawerIcon } = descriptors[route.key].options;

          return (
            <DrawerItem
              key={route.key}
              label={
                drawerLabel !== undefined
                  ? drawerLabel
                  : title !== undefined
                  ? title
                  : route.name
              }
              icon={drawerIcon}
              focused={focused}
              activeTintColor={activeTintColor}
              inactiveTintColor={inactiveTintColor}
              activeBackgroundColor={activeBackgroundColor}
              inactiveBackgroundColor={inactiveBackgroundColor}
              labelStyle={labelStyle}
              style={itemStyle}
              to={buildLink(route.name, route.params)}
              onPress={() => {
                navigation.dispatch({
                  ...(focused
                    ? DrawerActions.closeDrawer()
                    : CommonActions.navigate(route.name)),
                  target: state.key,
                });
              }}
            />
          );
        })}

完整的代码可以在这里找到-

https://gist.github.com/yashkumarsharma/a56f4fe1517ee8ce07c153d2d2795f6f

答案 4 :(得分:0)

@Lenin Sheikh 解决方案有效,但正如评论中强调的那样,它引入了另一个问题,即无法单击抽屉菜单中的某些组件。我通过使用两个步骤解决了这个问题(显然是在应用 @Lenin Sheikh 解决方案之后)。

  1. 将隐藏的项目移到列表底部

  2. 选择一个默认组件,特别是如果它是隐藏组件之一

    <Drawer.Navigator
              initialRouteName='Home'// Specify the default component
           drawerContent={
             (props) => (
               <DrawerList {...props} />)
           }>
    
           <Drawer.Screen name="Component 1"
                          component={Component1}
                          options={{ title: "Component one", headerShown: 
       false }} />
    
     <Drawer.Screen name="Component 2"
                      component={Component2}
                      options={{ title: "Component 2", headerShown: false 
    }} />
    
    
    
     <Drawer.Screen name="Logout"
                  component={LogoutPage}
                  options={{ title: "Logout", headerShown: true }} />
    
    <Drawer.Screen name="Home" component={HomePage}
                  options={{
                    title: "",
                    headerShown: false,
    
                  }} />//This is the hidden component
    
    </Drawer.Navigator>
    

答案 5 :(得分:0)

我刚刚找到了解决类似问题的方法。长话短说,我使用 Stack、Tabs 和 Drawer(用于汉堡菜单)。我设法组合了所有导航,但抽屉显示了我不想要的主页按钮。

我找到的解决方案在这里:

我也遇到了问题,即第一个抽屉菜单选项突出显示且不可点击。为此,我只需要将隐藏的菜单屏幕移动到抽屉导航的底部。 :) 我知道这不是最漂亮的解决方案,但我想我明白了。我希望它会帮助某人。这是我的代码:

function DrawerNavigator() {
  return (
    <NavigationContainer>
      <Drawer.Navigator
        initialRouteName="Home"
        drawerContent={props => {
          const filteredProps = {
            ...props,
            state: {
              ...props.state,
              routeNames: props.state.routeNames.filter(routeName => {
                routeName !== 'Home';
              }),
              routes: props.state.routes.filter(route => route.name !== 'Home'),
            },
          };
          return (
            <DrawerContentScrollView {...filteredProps}>
              <DrawerItemList {...filteredProps} />
            </DrawerContentScrollView>
          );
        }}>
        <Drawer.Screen name="Notifications" component={ProfileScreen} />
        <Drawer.Screen name="Notifications2" component={ProfileScreen} />
        <Drawer.Screen name="Home" component={StackNavigator} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}

附言所有屏幕都是假的,所以忽略它没有意义:)

当我睡个好觉并重构它时,我可以并且会分享我的整个导航,但不要犹豫,询问您是否需要更多代码。干杯!

答案 6 :(得分:0)

在我踏上 Github 上的 How to hide DrawerView.Item in DrawerNavigator contentComponent #795 之前,上述解决方案均不适合我。

其他人的评论使我能够为 react-native v5 提出一个动态且有效的解决方案。

const CustomDrawer = props => {
  const {state, descriptors, navigation} = props;
  const buildLink = useLinkBuilder();

  return (
    <DrawerContentScrollView {...props}>
      {state.routes.map((route, i) => {
        const isHidden = descriptors[route.key].options?.hidden; // <--- Added this line
        if (isHidden === true) return null; // <--- Added this line

        const focused = i === state.index;
        const {
          title,
          drawerLabel,
          drawerIcon,
          drawerActiveTintColor,
          drawerInactiveTintColor,
          drawerActiveBackgroundColor,
          drawerInactiveBackgroundColor,
          drawerLabelStyle,
          drawerItemStyle,
        } = descriptors[route.key].options;

        return (
          <DrawerItem
            key={route.key}
            label={
              drawerLabel !== undefined
                ? drawerLabel
                : title !== undefined
                ? title
                : route.name
            }
            icon={drawerIcon}
            focused={focused}
            activeTintColor={drawerActiveTintColor}
            inactiveTintColor={drawerInactiveTintColor}
            activeBackgroundColor={drawerActiveBackgroundColor}
            inactiveBackgroundColor={drawerInactiveBackgroundColor}
            labelStyle={drawerLabelStyle}
            style={drawerItemStyle}
            to={buildLink(route.name, route.params)}
            onPress={() => {
              navigation.dispatch({
                ...(focused
                  ? DrawerActions.closeDrawer()
                  : CommonActions.navigate(route.name)),
                target: state.key,
              });
            }}
          />
        );
      })}
    </DrawerContentScrollView>
  );
};

export default CustomDrawer;

然后你所要做的就是在 Drawer.Navigator 中使用 CustomDrawer 并将隐藏选项传递给 Drawer.Screen,如下所示:

<Drawer.Navigator
              initialRouteName={ROUTES.SIGN_IN}
              drawerPosition="right"
              drawerContent={props => <CustomDrawer {...props} />}>
              <Drawer.Screen
                name={ROUTES.SIGN_IN}
                component={SignInContainer}
                options={{headerShown: false, hidden: true}}
              />
              <Drawer.Screen
                name={ROUTES.DASHBOARD}
                component={withHeader(DashboardContainer)}
                options={{headerLeft: false}}
              />
</Drawer.Navigator>