如何手动在抽屉导航底部添加额外项目(如注销按钮)?

问题描述 投票:0回答:6

我想在 RN 应用程序的抽屉式导航底部添加注销按钮。

As you can see the Logout button is located at the bottom of the drawer menu. How can I move it to the bottom of the drawer panel?

我正在尝试按以下方式使用

contentComponent

const DrawerWithLogoutButton = (props) => (
  <ScrollView>
    <SafeAreaView style={styles.container} forceInset={{ top: 'always', horizontal: 'never' }}>
      <DrawerItems {...props} />
    </SafeAreaView>
    <Button
      style={styles.logoutButton}
      title="Logout"
      onPress={() => props.navigation.navigate('Login') }/>
  </ScrollView>
);

export default Home = createDrawerNavigator({
  // screens
}, {
  // other settings
  contentComponent: DrawerWithLogoutButton,
});

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
  },
  logoutButton: {
    backgroundColor: 'red',
    position: 'absolute',
    bottom: 0
  }
});

结果中,菜单底部有“注销”按钮。但我希望它位于抽屉面板的底部

我还希望“注销”按钮看起来像其他菜单项并有一个图标

有没有一种方法可以创建带有菜单项的抽屉导航器,该菜单项没有屏幕,但只是像我这样的注销之类的操作?

react-native navigation-drawer react-navigation
6个回答
17
投票

我能够通过将

justifyContent: 'space-between'
添加到
ScrollView
容器来对齐抽屉菜单底部的注销。你可以在图中看到结果

the Logout button is located at the bottom of the drawer menu

结果源代码如下所示:

const DrawerWithLogoutButton = (props) => (
  <ScrollView contentContainerStyle={{flex: 1,  flexDirection: 'column', justifyContent: 'space-between' }}>
    <SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
      <DrawerItems {...props} />
    </SafeAreaView>
    <TouchableOpacity>
      <View style={styles.item}>
        <View style={styles.iconContainer}>
          <Image source={require('./img/logout.png')} style={styles.icon}></Image>
        </View>
        <Text style={styles.label}>Logout</Text>
      </View>
    </TouchableOpacity>
  </ScrollView>
);

const styles = StyleSheet.create({
  item: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  label: {
    margin: 16,
    fontWeight: 'bold',
    color: 'rgba(0, 0, 0, .87)',
  },
  iconContainer: {
    marginHorizontal: 16,
    width: 24,
    alignItems: 'center',
  },
  icon: {
    width: 24,
    height: 24,
  }
});

8
投票

React Navigation 文档建议使用自定义内容抽屉功能包装抽屉导航。这就是我们所做的,为我们的抽屉提供一个注销按钮,同时也保留所有

Drawer.Screen
的位置。

在下面的代码中,我们创建一个

CustomDrawerContent
,其中包含
DrawerItem
作为我们的 logout 按钮。该函数通过其属性
Drawer.Navigator
包装
drawerContent
。我们最后的抽屉看起来像:

  • 首页(抽屉.屏幕)
  • 编辑个人资料(抽屉.屏幕)
  • 着陆(抽屉.屏幕)
  • 注销(抽屉项目)
const Drawer = createDrawerNavigator();

function CustomDrawerContent(props) {
  return (
    <DrawerContentScrollView {...props}>
      <DrawerItemList {...props} />
      <DrawerItem label={() => <Text style={{ color: 'white' }}>Logout</Text>}
        style={{backgroundColor: 'red'}} 
        onPress={() => alert('Logged out')}
      />
    </DrawerContentScrollView>
  );
}

function App(props) {
  return (
    <Provider store={store}>
      <View style={styles.container}>
        <StatusBar translucent={true} />
        <NavigationContainer>
          <Drawer.Navigator drawerContent={props => <CustomDrawerContent {...props} />}>
            <Drawer.Screen name='Home' component={Home} />
            <Drawer.Screen name='Edit Profile' component={EditProfile} />
            <Drawer.Screen name='Landing' component={Landing} />
          </Drawer.Navigator>
        </NavigationContainer>
      </View>
    </Provider>
  )
}

4
投票

与 William Griffins 的答案类似,只是他们的答案最终没有出现在抽屉底部的注销按钮。为了使注销位于底部,我将 DrawerContentScrollView 放入 SafeAreaView 中,然后在 DrawerContentScrollView 下方放置一个包含 DrawerItem(即注销按钮)的常规视图。

function CustomDrawerContent(props) {
    return (
        <SafeAreaView style={{flex: 1}} forceInset={{top: "always", horizontal: "never"}}>
            <DrawerContentScrollView {...props}>
                <DrawerItemList {...props} />
            </DrawerContentScrollView>
            <View>
                <DrawerItem label={"Logout"}
                            style={styles.logoutDrawerItem}
                            onPress={() => console.log('Logout pressed!')}
                />
            </View>
        </SafeAreaView>
    );
}

function App(props) {
  return (
    <Provider store={store}>
      <View style={styles.container}>
        <StatusBar translucent={true} />
        <NavigationContainer>
          <Drawer.Navigator drawerContent={props => <CustomDrawerContent {...props} />}>
            <Drawer.Screen name='Home' component={Home} />
            <Drawer.Screen name='Edit Profile' component={EditProfile} />
            <Drawer.Screen name='Landing' component={Landing} />
          </Drawer.Navigator>
        </NavigationContainer>
      </View>
    </Provider>
  )
}

const styles = StyleSheet.create({
    logoutDrawerItem: {
        borderRadius: 5,
    },
});

您放置在 DrawerContentScrollView 下方的任何项目都将放置在抽屉的底部。

请注意,我在注销 DrawerItem 上将 borderRadius 设置为 5,以便它与常规抽屉项目的边框半径紧密匹配。


2
投票

您可以像下面的代码一样设置

position:'absolute'
buttom:0

<TouchableOpacity 
    onPress={() => {this.logout()}}
    style={{ bottom: 0, position: 'absolute', width: '100%' }}>
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', flexDirection:'row', alignItems: 'center' }}>
        <Icon name="md-log-out" style={{marginRight: 10, color: '#444'}} size={20}/>
        <Text style={{color: '#444'}}>Logout</Text>
      </View>
</TouchableOpacity>

您可以更改样式,使其像其他按钮一样。我希望这能帮助你...


2
投票

接受的答案并没有直接适合我。我必须做一些修改,但总的来说,秘密确实是使用

justifyContent: 'space-between'

import {View} from 'react-native';
import {
  createDrawerNavigator,
  DrawerContentScrollView,
  DrawerItem,
  DrawerItemList,
  DrawerContentComponentProps,
} from '@react-navigation/drawer';

const Drawer = createDrawerNavigator();

function CustomDrawerContent(props: DrawerContentComponentProps) {
  return (
    <DrawerContentScrollView
      {...props}
      contentContainerStyle={{flex: 1, justifyContent: 'space-between'}}>
      <View style={{justifyContent: 'flex-start'}}>
        <DrawerItemList {...props} />
      </View>
      <DrawerItem
        label="Logout"
        onPress={() => console.log('Logged out')}
      />
    </DrawerContentScrollView>
  );
}

.
.
.

        <Drawer.Navigator
          initialRouteName="HomeScreen"
          drawerContent={(props) => <CustomDrawerContent {...props} />}
          drawerContentOptions={{
            activeTintColor: color.primaryDark,
            itemStyle: {
              backgroundColor: 'transperant',
              borderColor: color.primaryDark,
              borderBottomWidth: 1,
              opacity: 0.8,
            },
          }}
          drawerStyle={styles.drawer}>
          <Drawer.Screen name="Home" component={HomeScreen} />
          <Drawer.Screen name="Notifications" component={NotificationsScreen} />
        </Drawer.Navigator>

0
投票

版本:6.x 解决方案:

将 flex: 1 添加到抽屉内容容器样式,然后将 marginTop: "auto" 添加到最后一项。不需要抽屉内容。

    <Drawer
  screenOptions={{
    drawerContentContainerStyle: {
      flex: 1,
    },
  }}
>
  <Drawer.Screen
    name="index"
    options={{
      drawerLabel: "Home",
    }}
  />

  <Drawer.Screen
    name="logout"
    options={{
      drawerLabel: "Logout",
      drawerItemStyle: {
        marginTop: "auto",
      },
    }}
  />
</Drawer>;
© www.soinside.com 2019 - 2024. All rights reserved.