How to add extra item at the bottom of the drawer navigation manually (like logout button)?
Asked Answered
B

6

16

I want to add logout button to the bottom of the drawer navigation in my RN app.

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?

I am trying to use contentComponent the following way:

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

In the result I have the Logout button at the bottom of the menu. But I want it to be located at the bottom of the drawer panel instead

Also I would want the Logout button to look like other menu items and had an icon

Is there a way to create drawer navigator with a menu item which has no screen but is just an action like Logout as in my case?

Bey answered 9/6, 2018 at 16:43 Comment(2)
You should just set ScrollView flex: 1Saintly
@RomanOsypov thank you. I've tried to add style={{flex: 1}} to ScrollView but it didn't workBey
B
17

I was able to align Logout at the bottom of the drawer menu with adding justifyContent: 'space-between' to the ScrollView container. You can see the result in the picture

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

The result source code looks the following way:

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,
  }
});
Bey answered 11/6, 2018 at 8:44 Comment(0)
S
8

React Navigation docs recommend wrapping the drawer navigation with a custom content drawer function. This is what we do did to give our drawer a logout button, but also keep all of the Drawer.Screens in place.

In the code below we create a CustomDrawerContent that contains a DrawerItem as our logout button. This function wraps the Drawer.Navigator through its property drawerContent. Our final drawer then looks like:

  • Home (Drawer.Screen)
  • Edit Profile (Drawer.Screen)
  • Landing (Drawer.Screen)
  • Logout (DrawerItem)
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>
  )
}
Shredding answered 29/6, 2020 at 18:21 Comment(0)
T
4

Similar to William Griffins answer, except their answer does not end up with the logout button at the bottom of the drawer. To have logout be at the bottom, I put my DrawerContentScrollView inside a SafeAreaView, then beneath the DrawerContentScrollView I put a regular View containing the DrawerItem, which is the logout button.

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

Any items you place beneath the DrawerContentScrollView will be placed at the bottom of the drawer.

Note that I set borderRadius to 5 on the logout DrawerItem, so that it closely matches the border radius of regular drawer items.

Tena answered 19/11, 2020 at 2:11 Comment(0)
I
2

You can set position:'absolute' and buttom:0 like this code:

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

You can change the style to make it like other buttons. I hope this will help you...

Influence answered 10/6, 2018 at 6:10 Comment(1)
thank you for the help! I've tried your answer but it doesn't workBey
C
2

The accepted answer did not work out for me directly. I had to do some modifications, but in general the secret is indeed using 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>
Canaletto answered 19/4, 2021 at 12:19 Comment(0)
M
0

Version: 6.x solution:

Add flex: 1 to drawerContentContainerStyle and then marginTop: "auto" to the last item. No need for drawerContent.

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

  <Drawer.Screen
    name="logout"
    options={{
      drawerLabel: "Logout",
      drawerItemStyle: {
        marginTop: "auto",
      },
    }}
  />
</Drawer>;
Monomial answered 6/6 at 3:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.