how to add left border color to active drawer menu? - react-native

i am working on a react native 0.62 in which i have implemented drawer navigator. As per the documentation, i have properly added activeBackgroundColor, activeTintColor etc but as per the company's requirement, when the menu is active i wanted to add borderLeftColor also with activeBackgroundColor. i have tried using style property but it didn't work for me.
Mock Up:
My Current UI:
MainNavigator.js
<Drawer.Navigator initialRouteName="Dashboard" drawerContent={(props) => <DrawerContent {...props} />} hideStatusBar={false} focused={true} labelStyle={{ fontSize: 14, fontFamily: 'OpenSans-SemiBold' }} drawerContentOptions={{ activeBackgroundColor: "#F1F1F1", activeTintColor: "#000000", inactiveTintColor: "#818181",itemStyle: { marginLeft:0, paddingHorizontal: 10, width:'100%', borderRadius: 0}}} indicatorStyle={{
borderBottomWidth: 2,
borderBottomColor: 'red',
}}
>
<Drawer.Screen name="Dashboard" component={DashboardStackScreen} options={{
drawerIcon: ({ focused, size }) => (
<Image source={require('../assets/images/dashboard.png')} style={{ height: 17.78, width: 16}} resizeMode="contain"/>
),
}}
/>
<Drawer.Screen name="My Profile" component={MyProfileStackScreen} options={{
drawerIcon: ({ focused, size }) => (
<Image source={require('../assets/images/profile.png')} style={{ height: 16, width: 16 }} resizeMode="contain"/>
),
}} />
</Drawer.Navigator >
DrawerContent.js
<DrawerContentScrollView {...props} >
<DrawerItemList {...props}
/>
<DrawerItem
labelStyle={{ fontSize: 14, fontFamily: 'OpenSans-SemiBold' }} activeBackgroundColor= "#F1F1F1" activeTintColor="#000000" inactiveTintColor= "#818181"
label="Logout"
icon={({ focused, color, size })=>{
return(
<Image source={require('../assets/images/logout.png')} style={{ height: 14.36, width: 14.36 }} resizeMode="contain"/>)
}}
onPress={() => {resetData(); props.dispatch({type:'AUTH_FAILURE', payload: ''}); props.dispatch(onClear())} }
/>
</DrawerContentScrollView>
Thank you in advance.

As of now the drawer navigation 5 doesnt support an active style. But you can wrap the icon in a View and add a border to it which would give give you something similar.
Not the perfect solution but will get you close to the expected output you have provided.
<Drawer.Screen
name="My Profile"
component={MyProfileStackScreen}
options={{
drawerIcon: ({ focused, size }) => (
<View
style={
focused
? {
borderLeftColor: 'red',
borderLeftWidth: 2,
paddingLeft: 5,
}
: null
}>
<Image
source={require('../assets/images/profile.png')}
style={{ height: 17.78, width: 16 }}
resizeMode="contain"
/>
</View>
),
}}
/>

I know I am too late, but may be helpful in future for someone
I achieved the design by doing like below,
here is my CustomDrawerComponent
I used props -> state object to identify the active route name
Then apply conditional styles to <DrawerItem style={{}}/>
import { createDrawerNavigator } from '#react-navigation/drawer';
import {DrawerItem,DrawerContentScrollView} from '#react-navigation/drawer';
const CustomDrawerContent = props => {
const {state} = props;
const {routes, index} = state;
//here we get the active route name
const focusedRoute = routes[index].name;
return (
<View style={{flex: 1}}>
<ProfileHeader />
<DrawerContentScrollView
{...props}
contentContainerStyle={{paddingTop: 0, flex: 1}}>
<DrawerItem
{...props}
label="Screen1"
style={
focusedRoute === 'Screen1' ? styles.itemActive : styles.itemInactive
}
labelStyle={{}}
icon={({}) => <Icon />}
onPress={() => {
props.navigation.navigate('Screen1');
}}
/>
<DrawerItem
{...props}
label="Screen1"
style={
focusedRoute === 'Screen2' ? styles.itemActive : styles.itemInactive
}
labelStyle={{}}
icon={({}) => <Icon />}
onPress={() => {
props.navigation.navigate('Screen2');
}}
/>
<DrawerItem
{...props}
label="Logout"
style={styles.itemInactive}
labelStyle={{}}
icon={({}) => <Icon />}
/>
</DrawerContentScrollView>
</View>
);
};
Here is my Root Drawer.Navigator setup
<Drawer.Navigator
drawerContent={props => <CustomDrawerContent {...props} />}>
// Drawer Screens
</Drawer.Navigator>

Related

React native Drawer Navigator item space

I'm using the react native drawer navigator v6 and I would like to reduce the space between the items and also the space between icon and label, see screenshot:
Does somebody know how?
Thanks!
My custom drawer:
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView
{...props}
contentContainerStyle={{ paddingTop: 0 }}
>
<View style={styles.logo}>
<Image source={require("../assets/images/logo.png")} />
</View>
<DrawerItemList {...props} style={{ paddingTop: 0, marginTop: 0 }} />
</DrawerContentScrollView>
);
}
And my drawer navigator:
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContent {...props} />}
screenOptions={{
gestureEnabled: true,
headerTitleAlign: "center",
headerStyle: {
backgroundColor: "#82bf4e",
borderBottomWidth: 0.5,
shadowColor: "transparent",
borderBottomColor: "#75ad46",
},
headerTitleStyle: {
fontSize: 18,
},
headerTintColor: "#fff",
headerLeft: () => <BackButton />,
}}
>
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{
header: () => <HeaderContainer />,
drawerItemStyle: { display: "none" },
}}
/>
<Drawer.Screen
name="Mein Team"
component={TeamScreen}
options={{
headerTitle: "Mein Team",
drawerIcon: () => <AntDesign size={20} name="team" />,
}}
/>
...
</Drawer.Navigator>
You can create custom navigator using
<Drawer.Navigator drawerContent={(props) => <CustomDrawerContent {...props} />}>
{/* screens */}
</Drawer.Navigator>
Adjust the spacing as you want.

How to make activeTIntColor and activebackgroundColor of drawerItem work in react navigation 6?

I was not able to change the activeTintColor and activeBackgroundColor of drawerItem in react-navigation 6, Eventhough I'm using those props on drawer item I can't see any changes in activeItem tintColor change in selected Item.Below here is the code that I'm using where I used the prop activeTintColor to set the active DrawerItem tint color but I don't see any changes in color and even I can't see which is active tab I'm on but navigation works fine.I am able to navigate to DrawerItem screens only thing it active Item which is selected doesn't seems applying activeTintColor etc
function DrawerNavigation() {
return (
<NavigationContainer>
<Drawer.Navigator
screenOptions={{
headerShown: false
}}
drawerContent={(nav) => {
const { navigation } = nav;
let state = navigation.getState();
return (
<View style={{ flex: 1 }}>
<View style={{ alignItems: "center" }}>
<View
style={{
height: 100,
width: 100,
borderColor: "black",
borderWidth: 1,
borderRadius: 50,
marginVertical: 10,
overflow: "hidden"
}}
>
<Image
source={{
uri: "https://m.cricbuzz.com/a/img/v1/192x192/i1/c170661/virat-kohli.jpg"
}}
resizeMode="cover"
style={{ width: "100%", height: "100%" }}
/>
</View>
</View>
<View style={{ flex: 1 }}>
<DrawerItem
label="Home"
pressColor="red"
icon={() => (
<Image
source={require("../assets/home.png")}
style={{ height: 25, width: 25 }}
/>
)}
onPress={() => navigation.navigate("Home")}
activeTintColor="red"
/>
<DrawerItem
label="Profile"
pressColor="red"
icon={() => (
<Image
source={require("../assets/profile.png")}
style={{ height: 25, width: 25 }}
/>
)}
onPress={() => navigation.navigate("Profile")}
activeTintColor="red"
/>
<DrawerItem
label="Cart"
pressColor="red"
icon={() => (
<Image
source={require("../assets/cart.png")}
style={{ height: 25, width: 25 }}
/>
)}
onPress={() => navigation.navigate("Cart")}
activeTintColor="red"
/>
</View>
</View>
);
}}
>
<Drawer.Screen name="HomeStack" component={StackNavigation} />
</Drawer.Navigator>
</NavigationContainer>
);
}
i was facing a similar issue cause i be working with react-navigator 6.x but read the 5.x doc. To set the activeTintColor to all my screens i finnaly do it like that:
<NavigationContainer>
<Drawer.Navigator
screenOptions={{
drawerStyle: {
backgroundColor: "grey",
width: "100%",
},
drawerActiveTintColor: "white",
drawerInactiveTintColor: "yellow",
}}
>
<Drawer.Screen
name="One"
component={OneStackScreen}
options={{
title: "One",
drawerIcon: () => (
<MaterialIcons name="home" size={24} color="white" />
),
}}
/>
<Drawer.Screen
name="Two"
component={TwoStackScreen}
options={{
title: "Ma page",
}}
/>
</Drawer.Navigator>
</NavigationContainer>
in your <Drawer.Navigator/> There is a property named option which takes an
object and in that object you can find the drawerActiveTintColor Property. That
can be used to set the activeTintColor and it will change the background color
as well.
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen}
options={{ drawerActiveTintColor: 'red' }}/>
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
<DrawerContentScrollView {...props}>
<View style={Styles.DrawerHeader}>
<View style={Styles.ProfileImg}>
{userPic ? (
<Image
source={{
uri: userPic
}}
resizeMode="cover"
style={{ width: "100%", height: "100%" }}
/>
) : (
<Image
source={{
uri: "https://m.cricbuzz.com/a/img/v1/192x192/i1/c170661/virat-kohli.jpg"
}}
resizeMode="cover"
style={{ width: "100%", height: "100%" }}
/>
)}
</View>
<Text style={Styles.ProfileText}>{user}</Text>
</View>
<View style={Styles.Divider}></View>
{state.routes.map((route) => {
return (
<DrawerItem
key={route.key}
icon={({ focused }) => (
<Icon name={listItemIcon} size={20} color={focused ? Colors.Primary : "black"} />
)}
label={({ color }) => <Text style={{ color }}>{route.name}</Text>}
focused={state.routes.findIndex((e) => e.name === route.name) === state.index}
activeTintColor={Colors.Primary}
onPress={() => navigation.navigate(route.name)}
pressColor={Colors.StatusbarColor}
/>
);
})}
</DrawerContentScrollView>

Can't change screen with TabIcon in react native?

I have an issue when changing screens. If i pressed in the middle of the tabIcon it's not navigating to the screen but if i clicked a little bit left further the screen changes. I think that like there is a sort of a View in absolute above that is preventing me from pressing (Element inspector).
I have my code like this :
<Tab.Navigator
initialRouteName="HomeNavigator"
tabBarOptions={{
showLabel: false,
keyboardHidesTabBar: true,
labelStyle: {
color: 'red'
},
style: {
backgroundColor: '#008D36' ,
paddingTop: 10,
paddingBottom: 10,
minHeight: 65,
color: '#ffffff',
borderTopColor: '#ffffff',
justifyContent: 'flex-start',
alignItems: 'flex-start'
, }
}}
>
<Tab.Screen
name="Home"
component={HomeNavigator}
options={(navigation, route) => ({
title: 'Home',
tabBarIcon: ({ props, focused }) => (
<TouchableWithoutFeedback {...props} >
<View style={{flex: 2, alignItems: 'center'}}>
<Image source={LOGO1} resizeMode="contain" style={[styles.imgSize, focused && { opacity:1 }]} />
<Text style={[styles.label, focused && { opacity:1, textDecorationLine: 'underline' }]}>Home</Text>
</View>
</TouchableWithoutFeedback>
)
})}
/>
<Tab.Screen
name="Home2"
component={HomeNavigator}
options={(navigation, route) => ({
title: 'Home2',
tabBarIcon: ({ props, focused }) => (
<TouchableWithoutFeedback {...props} >
<View style={{flex: 2, alignItems: 'center'}}>
<Image source={LOGO2} resizeMode="contain" style={[styles.imgSize, focused && { opacity:1 }]} />
<Text style={[styles.label, focused && { opacity:1, textDecorationLine: 'underline' }]}>Home2</Text>
</View>
</TouchableWithoutFeedback>
)
})}
/>
</Tab.Navigator>
I think that flex: 2 is out of place at this position of the tabBarIcon. You can use alignItems or justifyContent without telling the view for flex.
<TouchableWithoutFeedback {...props} >
<View style={{alignItems: 'center'}}>
<Image source={LOGO1} resizeMode="contain" style={[styles.imgSize, focused && { opacity:1 }]} />
<Text style={[styles.label, focused && { opacity:1, textDecorationLine: 'underline' }]}>Home</Text>
</View>
</TouchableWithoutFeedback>

How to navigate to another screen using DrawerItem

Im stuck with navigation in Navigation Drawer
my partner did this part of the code and he added DrawerItem(Which will be seen to every user(Admin/client)
i cant figure out how to navigate with it. i tried navigation.navigate("") and its not working
<DrawerItem
label="הגדרות"
style={{
position: "absolute",
bottom: 0,
right: 0,
left: 0,
marginBottom: 60,
borderTopColor: "#afafaf",
borderTopWidth: 3,
}}
onPress={() => logOut()} //Here i need to navigate to the page "aboutUs"
icon={({ color, size }) => (
<MaterialIcons name="settings" color={color} size={size} />
)}
/>
About us stack screen:
const Stack = createStackNavigator();
const aboutStack = ({ navigation }) => {
return (
<Stack.Navigator
initialRouteName={"Aboutus"}
screenOptions={{
headerLeft: () => (
<SimpleLineIcons
name="menu"
style={{ marginLeft: 20 }}
size={24}
color="black"
onPress={() => navigation.toggleDrawer()}
/>
),
}}
>
<Stack.Screen
name="קצת עלינו"
component={Aboutus}
options={{ headerTitleAlign: "center" }}
/>
</Stack.Navigator>
);
};
export default aboutStack;
You can use the props that are passed to the custom drawer and navigate using the name of the screen like below.
onPress={() => props.navigaton.navigate("קצת עלינו")}

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

I want to add logout button to the bottom of the drawer navigation in my RN app.
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?
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 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,
}
});
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>
)
}
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.
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...
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>