React-navigation default drawer icon, how to change it? - react-native

How can I change the icon point in the image below? I have not been able to find the documentation in the docs, I would like to change it to a different icon but I have no idea how to do this.
I found documentation about drawerIcon but as far as I know and manage to implement that icon is for the menu items in the drawer it self not for the screen header.
Here is my code:
const Drawer = createDrawerNavigator();
const headerOptions = {
title: 'Task List',
drawerIcon: ({ focused, size, color }) => <Ionicons name="ios-pizza" color="red" size={24} />,
};
const HomeScreen = ({ navigation }, props) => {
return (
<Drawer.Navigator screenOptions={{ drawerType: 'front' }}>
<Drawer.Screen name="TaskList" component={TaskListScreen} options={headerOptions} />
<Drawer.Screen name="TaskView" component={TaskViewScreen} />
<Drawer.Screen name="Notifications" component={Notifications} />
<Drawer.Screen name="Login" component={LoginScreen} />
</Drawer.Navigator>
);
};
But as mention before it renders the icons in the drawer item as shown below

headerLeft: Function which returns a React Element to display on the left side of the header. You can use it to implement your custom left button, for example:
<Drawer.Navigator
screenOptions={({ navigation }) => ({
headerLeft: props => <IconComponent onPress={navigation.toggleDrawer} />,
})}
>
...
</Drawer.Navigator>

<Drawer.Navigator
screenOptions={{
headerTintColor: 'red', // -----> by changing color from here
}} drawerContent={props => <DrawerContent {...props} />} >
<Drawer.Screen />
</Drawer.Navigator >

you can also use a image as a drawer icon.
screenOptions={({ navigation }) => ({
headerLeft: () =>
<Pressable onPress={navigation.toggleDrawer}>
<Text>
<Avatar.Image size={32} source={{ uri: deafaultImage }} />
</Text>
</Pressable >
})}

Related

Turning off the drawer header in a specific screen in bottom tab navigation in drawer navigation in react native

I have a very big problem I am using two navigations in one app the first one is the drawer navigator this is how I use the drawer navigator:
<Drawer.Navigator
screenOptions={{
drawerStyle: {
backgroundColor: 'white',
},
}}
drawerContent={props => <CustomSidebarMenu {...props} />}
drawerContentOptions={{
activeTintColor: '#e91e63',
activeBackgroundColor: 'red',
itemStyle: {marginVertical: 20},
}}>
<Drawer.Screen
options={{
headerShown: true,
headerTitle: () => (
<Image
style={{height: 150, width: 100, resizeMode: 'contain'}}
source={require('../assets/images/referans2.png')}
/>
), // Title to appear in the header
headerRight: ({navigation, scene}) => (
// Custom component to appear on the right side of the header
<View style={{flexDirection: 'row'}}>
<Pressable>
<Ionicons
name="notifications-outline"
size={30}
color={'black'}
/>
</Pressable>
<Pressable style={{marginHorizontal: 10}}>
<Ionicons
name="chatbubbles-outline"
size={30}
color={'black'}
/>
</Pressable>
</View>
),
}}
name="Ana Sayfa"
component={Main}
/>
<Drawer.Screen
options={{headerShown: true}}
name="Şiparişlerim"
component={MyOrders}
/>
<Drawer.Screen name="Adreslerim" component={AddressesScreen} />
<Drawer.Screen name="Üyelik Bilgilerim" component={AccountInfoScreen} />
</Drawer.Navigator>
[
and this gives me the following output:](https://i.stack.imgur.com/73o8f.png)
In the main function you see here, the bottomtabnavigator, which I use in the whole app, returns.:
const Main = () => {
return (
<Tab.Navigator screenOptions={screenOptions}>
<Tab.Screen
component={HomeStack}
name="Ana Sayfa"
options={{
tabBarIcon: ({focused, color}) => (
<Ionicons name="home-outline" size={28} color={color} />
),
}}
/>
<Tab.Screen
component={CategoriesStack}
name="Kategoriler"
options={{
tabBarIcon: ({focused, color}) => (
<Ionicons name="grid-outline" size={28} color={color} />
),
}}
/>
<Tab.Screen
component={CartStack}
name="Sepet"
options={{
tabBarIcon: ({focused, color}) => (
<Ionicons name="cart-outline" size={28} color={color} />
),
}}
/>
<Tab.Screen
component={DiscoverStack}
name="Keşfet"
options={{
tabBarIcon: ({focused, color}) => (
<Ionicons name="compass-outline" size={28} color={color} />
),
}}
/>
<Tab.Screen
component={ProfileStack}
name="Profilim"
options={{
headerShown: true,
tabBarIcon: ({focused, color}) => (
<Ionicons name="person-circle-outline" size={28} color={color} />
),
}}
/>
</Tab.Navigator>
);
};
What I want is this; Turning off the header of the drawer in the profile stack in the bottom tab navigator, but I can't do it
but it still didn't close the header of the drawer navigation. Even if I set the headershown of the drawer to false, the header on all screens closes, I'm just not on the screen I want
As far as I understand, there are 3 nested navigator.
Drawer
|---------> BottomTab
| |---------> ProfileStack
|... |...
If you want to hide or show only specific screen you can use navigation.setOptions()
For example,we have a Profile screen in ProfileStack and get navigation with screen props or useNavigation()
If you want to hide ProfileStack header in Profile:
React.useLayoutEffect(() => {
navigation.setOptions({ headerShown:false })
})
If you want to hide BottomTab header in Profile:
React.useLayoutEffect(() => {
navigation.getParent().setOptions({ headerShown:false })
})
If you want to hide Drawer header in Profile:
React.useLayoutEffect(() => {
navigation.getParent().getParent().setOptions({ headerShown:false })
})
You can use setOptions with headerShown:true when the drawer screenOptions headerShown:false
react-navigation getParent() and setOptions() docs

React Native Drawer Navigation show headerLeft

I have a Drawer navigator which is inside a Stack navigator and I'd like to display a header. Currently I can display everything I want however because the header is defined at the Stack level the navigation inside the header is stack level not drawer level which is preventing me from opening the drawer.
Root stack
<Stack.Navigator
initialRouteName={"Splash"}
screenOptions={{}}
component={SplashScreen}
>
{ auth ?
<Stack.Screen name="Drawer" component={DrawerStack} options={({ navigation }) => ({
title: 'My App',
headerLeft: () => (
<HeaderLeft navigation={ navigation } />
),
headerRight: () => (
<HeaderRight navigation={ navigation } />
),
headerTitleAlign: 'center',
headerTintColor: 'white',
headerStyle: {
backgroundColor: '#5742f5'
},
})} />
:
<Stack.Screen name="Auth" component={AuthStack} options={{
headerShown: false
}}/>
}
</Stack.Navigator>
Drawer stack
<Drawer.Navigator options={{
headerShown: true,
headerLeft: () => (
<HeaderLeft navigation={ navigation } />
),
}}>
<Drawer.Screen
name="Conversations"
options={{
title: props.title,
}}
component={ChatListScreen}
/>
<Drawer.Screen
name="ChatRoom"
options={{
drawerLabel: () => null,
title: null,
drawerIcon: () => null
}}
component={ChatRoomScreen}
/>
</Drawer.Navigator>
Note in the drawer navigator the line with headerLeft does nothing and is there to show where I attempted to put it thinking it would work. I did think it might be overlaying the stack one so I commented out the stack one and it didn't work.
HeaderLeft
export default function HeaderLeft ({ navigation }) {
const openMenu = () => {
navigation.toggleDrawer();
}
return (
<View style={styles.header}>
<Icon name='menu' onPress={openMenu} size={28} style={styles.icon} color="white"/>
</View>
)
}
My question is how can I refactor this to enable me to have the HeaderLeft component work to open the drawer. I will be adding more screens so ideally something I don't have to pass to each screen but if that is what works I am good with it too.
Options in DrawerStack not work. I modified it:
<Drawer.Navigator
screenOptions={{
headerLeft: () => <HeaderLeft />,
}}>
// ...
</Drawer.Navigator>
And a little change in HeaderLeft:
import { useNavigation } from '#react-navigation/native';
function HeaderLeft() {
const navigation = useNavigation();
const openMenu = () => {
navigation.toggleDrawer();
};
// render your Button
}
Demo: https://snack.expo.dev/#pqv2210/0d613b

Is it possible to have a left and right drawer menu in the same header using React Native Navigation 6?

I've found various examples using version 5 like this https://snack.expo.dev/Bkd0MKqb7 but can't seem to get this working using version 6.
Here's a snippet of my code showing the main drawer menu which is set to the left and then there is a nested drawer menu which is positioned to the right. When the button is clicked it opens the left menu, not the right. Is this possible?
This is how it looks so far...
Two drawers on the same page, but not in the same header
Thanks.
const MainDrawerNavigator = () => {
return (
<Drawer.Navigator screenOptions={{ drawerPosition: "left" }}>
<Drawer.Screen
name="Home"
component={RightDrawerNavigator}
options={({ navigation }) => ({
headerRight: () => (
<Button
onPress={() => navigation.toggleDrawer()}
title="Options"
color="#000000"
/>
),
})}
/>
</Drawer.Navigator>
);
};
Here's the right drawer code:
const RightDrawerNavigator = () => {
return (
<Drawer.Navigator initialRouteName="TeamScreen" screenOptions={{ drawerPosition: "right", drawerType: "slide" }}>
<Drawer.Screen name="TeamScreen" component={TeamScreen} options={{ headerShown: false, title: 'Team Home' }} />
</Drawer.Navigator>
);
};

How to keep track of screen title when bottom navigation is used in react native?

I am making use of bottom navigation in React Native and I have a header which is supposed to show on which screen I am at the moment. I am not sure how to change that text on Tab Bar press. I tried making use of onPress event but seems like it does not work.
Here is my code:
<View style={styles.container}>
<StatusBar barStyle="light-content" />
<View style={styles.header}>
<Text style={styles.headerText}>{headerText}</Text>
<SettingsIcon />
</View>
<View style={styles.main}>
<NavigationContainer >
<Tab.Navigator initialRouteName="Home" tabBarOptions={{
activeTintColor: '#FF9F0A',
inactiveTintColor:'white',
style: {
backgroundColor: '#000000',//color you want to change
}
}}>
<Tab.Screen name="Home" component={Home} options={{
tabBarLabel: 'HOME',
tabBarIcon: ({ color, size }) => (
<HomeTabIcon name="home" color={color} size={size} />
),
}}/>
<Tab.Screen name="Controls" component={Controls} options={{
tabBarLabel: 'CONTROLS',
tabBarIcon: ({ color, size }) => (
<ControlsTabIcon name="controls" color={color} size={size} />
),
}}/>
<Tab.Screen name="Charging" component={Charging} options={{
tabBarLabel: 'CHARGING',
tabBarIcon: ({ color, size }) => (
<ChargingTabIcon name="charging" color={color} size={size} />
),
}}/>
</Tab.Navigator>
</NavigationContainer>
</View>
</View>
you can nest your tab navigator in a screen navigator.
You can change the title of your screen navigator header in function of the name of your active screen.
for more information read this.
import React from 'react';
import { NavigationContainer, getFocusedRouteNameFromRoute } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const RootStack = createStackNavigator();
const Tab = createBottomTabNavigator();
function getHeaderTitle(route : any) {
// If the focused route is not found, we need to assume it's the initial screen
// This can happen during if there hasn't been any navigation inside the screen
// In our case, it's "Feed" as that's the first screen inside the navigator
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Home';
console.log("name route = ", routeName);
switch (routeName) {
case 'Home':
return 'name header tab1';
case 'tab1':
return 'name header tab1';
case 'tab2':
return 'name header tab2';
}
}
const HomeTabs = () => {
return (
<Tab.Navigator>
<Tab.Screen name="tab1" component={Component1} />
<Tab.Screen name="tab2" component={Component2} />
</Tab.Navigator>
);
};
function Root() {
return (
<NavigationContainer>
<RootStack.Navigator>
<RootStack.Screen
name="Home"
component={HomeTabs}
options={({ route }) => ({
headerTitle: getHeaderTitle(route),
})}
/>
</RootStack.Navigator>
</NavigationContainer>
);
};

React Native - Trying to create a drawer with tabs navigators in react navigation without the Drawer Item of the Tabs being rendered

I am trying to create an app where I have a drawer and tabs navigators on each page.
I followed various tutorials and the react navigation docs but could not find a solution.
I have created a drawer navigator and within the <drawer.screen/> component I put my main tab navigator (My Tab navigator has multiple stacks - HomeStack, JoinStack, etc). So far so good however when I navigate to that main tab label in the menu, I return to the same screen I came from last and not to the top of my HomeStack although the "initialRouteName" is set to "Home".
I decided to leave it but remove the label, however it does not remove it completely. It removes the text but still there is a component being rendered there (see Image1 below)
Image1:
DrawerItem still being rendered
DrawerNavigator.js
//imports and stuff
const Drawer = createDrawerNavigator();
function MyDrawer({logout}) {
const nav = useNavigation()
return (
<Drawer.Navigator
initialRouteName={stackNavigationsConsts.HOME_STACK}
drawerPosition="right"
drawerContent={(props) => {
return (
<CustomDrawer nav={nav} drawerProps={props}/>
)
}}
>
<Drawer.Screen name={"בדיקה"} component={MainTabNavigator} options={{drawerLabel: () => null}}/>
<Drawer.Screen name="מאמר" component={Article} />
</Drawer.Navigator>
);
}
MainTabNavigator.js
//imports and stuff
const Tab = createBottomTabNavigator();
export default function MainTabNavigator() {
return (
<Tab.Navigator
initialRouteName={stackNavigationsConsts.HOME_STACK}
tabBarOptions={{
activeTintColor: mainColor.secondaryColor,
inactiveTintColor: mainColor.text,
activeBackgroundColor: mainColor.MainBackgroundColor,
// activeBackgroundColor: mainColor.buttonPress,
inactiveBackgroundColor: mainColor.MainBackgroundColor,
keyboardHidesTabBar: true,
}}
>
<Tab.Screen name={stackNavigationsConsts.HOME_STACK} component={HomeStackScreens}
options={{
tabBarLabel: navigationConsts.HOME,
tabBarIcon: ({ color, size }) => (
homeIcon(color)
),
}}
/>
<Tab.Screen name={stackNavigationsConsts.PROFILE_STACK} component={AnotherStack2Screen} options={{
tabBarLabel: navigationConsts.PROFILE ,
tabBarIcon: ({ color, size }) => (
profileIcon(color)
),
}}/>
<Tab.Screen name={stackNavigationsConsts.JOIN_STACK} component={JoinStackScreens}
options={{
tabBarLabel: navigationConsts.JOIN ,
tabBarIcon: ({ color, size }) => (
JoinIcon(color)
),
}}/>
<Tab.Screen name={stackNavigationsConsts.NOTIFICATIONS_STACK} component={AnotherStackScreen} options={{
tabBarLabel: navigationConsts.NOTIFICATIONS ,
tabBarIcon: ({ color, size }) => (
messagesIcon(color)
),
tabBarBadge: 12
}}/>
<Tab.Screen name={stackNavigationsConsts.ADD_RIDE_STACK} component={AnotherStack1Screen} options={{
tabBarLabel: navigationConsts.ADD_RIDE ,
tabBarIcon: ({ color, size }) => (
addRideIcon(color)
),
}}/>
</Tab.Navigator>
);
}
I found the solution here - How to hide Drawer Item from Drawer #2021 There is a workaround from v5 onward, need to extract the list of routes from the drawer navigation state and filter out the label you don't want to as I understood and it worked perfectly!
Please see below my render function for the custom drawer:
render() {
const {state, ...rest} = this.props.drawerProps
const newState = {...state}
newState.routes = newState.routes.filter((item) => item.name !== "זמני")
return (
<DrawerContentScrollView {...this.props}
>
<View style={styles.avatar}>
<View style={styles.imageContainer}>
<Image style={styles.image} source={require('../../../assets/images/man_smile.png')}/>
<Text style={{...styles.text, fontSize:22, marginTop:5}}>גלעד דהן</Text>
</View>
</View>
<View style={styles.items}>
<DrawerItemList
state={newState}
{...rest}
/>
<DrawerItem label={navigationConsts.MAIN} onPress={() => this.props.nav.navigate(stackNavigationsConsts.HOME_STACK)} labelStyle={styles.text}/>
<DrawerItem label="התנתק" onPress={() => this.props.logout()} labelStyle={styles.text}/>
</View>
</DrawerContentScrollView>