ReactNative how to disable click on drawer menu item - react-native

the drawer menu setup is like below.
how can i disable click on first Drawer.Screen ?
it must show a single image!!
also how can i hide one element programmatically?
<Drawer.Navigator
initialRouteName="Feed"
drawerPosition="right"
drawerStyle={{
backgroundColor: '#c7c4b8',
width: 240,
}}
overlayColor="transparent">
<Drawer.Screen
name="Profile2"
component={Profile2}
options={{ drawerLabel: '', drawerIcon: ({ focused, size }) => (
<Image source={require('./images/3.jpg')} resizeMode={'cover'} style={{ width: '100%', height: 200 }} />)
}}
/>
<Drawer.Screen
name="Home"
component={Notifications}
options={{ drawerLabel: 'Feed' }}
/>
<Drawer.Screen
name="Routes"
component={Profile}
options={{ drawerLabel: 'Routes' }}
/>
</Drawer.Navigator>

For add header or whatever you want you should use drawerContent prop and there you can make your custom drawer or manipulate the existing one like in the example below.
For show/hide screen in a drawer programatically you can just use it with useState or pass a redux store and conditionally render it or not, remember that navigator its just a react component.
I let you a snack to check it online as well.
https://snack.expo.io/#anthowm/drawer-navigation-%7C-react-navigation
import * as React from 'react';
import {useState} from 'react';
import { View, Text, Image } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItemList,
DrawerItem,
} from '#react-navigation/drawer';
function Feed() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Feed Screen</Text>
</View>
);
}
function Article() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Article Screen</Text>
</View>
);
}
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<Image source={{
uri: 'https://reactnative.dev/img/tiny_logo.png',
}} resizeMode={'cover'} style={{ width: '100%', height: 200 }} />
<DrawerItemList {...props} />
<DrawerItem
label="Hide Screen"
onPress={() => props.setShow(false)}
/>
</DrawerContentScrollView>
);
}
const Drawer = createDrawerNavigator();
function MyDrawer() {
const [show, setShow] = useState(true);
return (
<Drawer.Navigator drawerContent={props => <CustomDrawerContent setShow={setShow} {...props} />}>
<Drawer.Screen name="Feed" component={Feed} />
{show && <Drawer.Screen name="Article" component={Article} />}
</Drawer.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyDrawer />
</NavigationContainer>
);
}

Related

What is the proper way to have only one header with Open Drawer and Back button?

What I need is a single header with a back button on StackScreen2 and a toggle drawer button in StackScreen1.
I apologise for my poor writing and English.
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
function StackScreen1({ navigation }) {
return (
<View>
<Text>StackScreen1</Text>
<Button title="Go To StackScreen2" onPress={() => navigation.navigate("StackScreen2")} />
</View>
)
}
function StackScreen2() {
return (
<View>
<Text>StackScreen2</Text>
</View>
)
}
function DrawerScreen1() {
return (
<Stack.Navigator>
<Stack.Screen name="StackScreen1" component={StackScreen1} />
<Stack.Screen name="StackScreen2" component={StackScreen2} />
</Stack.Navigator>
)
}
function DrawerScreen2() {
return (
<View>
<Text>DrawerScreen2</Text>
</View>
)
}
const Drawer = createDrawerNavigator();
export default function Test3() {
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="DrawerScreen1" component={DrawerScreen1} />
<Drawer.Screen name="DrawerScreen2" component={DrawerScreen2} />
</Drawer.Navigator>
</NavigationContainer>
);
}
StackScreen1
StackScreen2
I tried hiding drawer header but then I don't have toggle drawer button anywhere.
Check below code for drawer navigation:
import * as React from 'react';
import { Button, View } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => navigation.navigate('Notifications')}
title="Go to notifications"
/>
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator useLegacyImplementation initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
You can check more about drawer here.
May be this will help you!
import * as React from 'react';
import { Ionicons, FontAwesome } from '#expo/vector-icons';
import { Button, View, Text, Pressable,Image } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createDrawerNavigator } from '#react-navigation/drawer';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('SettingsScreen')}
/>
</View>
);
}
function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.goBack()}
/>
</View>
);
}
const Drawer = createDrawerNavigator();
function MyDrawer() {
return (
<Drawer.Navigator
useLegacyImplementation
// screenOptions={{
// drawerLabelStyle: { fontSize: 17, color: '#000',marginLeft:-30 }
// }}
>
<Drawer.Screen
name="HomeScreen"
component={DetailsScreen}
screenOptions={{
headerShown: false,
}}
/>
</Drawer.Navigator>
);
}
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen
name="SettingsScreen"
component={MyDrawer}
options={{
headerShown: false,
tabBarIcon: ({ color, size }) => (
<Ionicons name="md-home" size={24} color={'#eee'} />
),
tabBarStyle: { position: 'absolute' },
tabBarActiveTintColor: '#eee',
tabBarInactiveTintColor: '#eee',
}}
/>
<Tab.Screen
name="DetailsScreen"
component={DetailsScreen}
options={{
headerShown: false,
tabBarIcon: ({ color, size }) => (
<Image source={{uri:"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTUAN0zLcvLFjdaYN1dBRSKoIuJndRW6VuX85w2yzEzxvTwO3B0Y_gv1x8kVDISNKJEbq0&usqp=CAU"}}
style={{width:24,height:24,borderRadius:24}} />
),
tabBarStyle: { position: 'absolute' },
tabBarActiveTintColor: '#eee',
tabBarInactiveTintColor: '#eee',
}}
/>
</Tab.Navigator>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>2</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="HomeScreen">
<Stack.Screen
name="HomeScreen"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="SettingsScreen"
component={MyTabs}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;

How to make headerTitle to fit into headerBackground with react navigation?

I am using the react navigation library with react native, I want to create a custom header by using the headerBackground and headerTitle screen options.
I need a robust way for the headerTitle component to use all the available space, but remains inside the limits of the screen.
So far I have (Snack link):
function App(): JSX.Element {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
options={{
headerBackground: () => (
<View
style={{
flex: 1,
backgroundColor: 'red',
borderColor: 'green',
borderWidth: 4,
}}
/>
),
headerTitle: props => (
<View
style={{
backgroundColor: 'blue',
flex: 1,
}}>
<Text>Header Title</Text>
</View>
),
}}>
{() => <SafeAreaView />}
</Stack.Screen>
</Stack.Navigator>
</NavigationContainer>
);
}
Note I have inlined styles and other bad practices just to make the code shorter for this question.
The results is the following:
Note how the headerTitle component grows without limits.
Is there a robust way to deal with this issue ? Note I am trying to avoid getting/using the dimensions of the device, as in the header can be other content such as backButton, or other options buttons on the right side.
Thanks in advance.
here is code example you can see to run this code may be this will help you:)
App.js
import * as React from 'react';
import {
Button,
View,
Text,
ImageBackground,
StyleSheet,
TouchableOpacity,
Image
} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const image = { uri: 'https://reactjs.org/logo-og.png' };
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function DetailsScreen({ navigation }) {
return (
<View style={{}}>
<ImageBackground source={image} style={styles.image}>
<TouchableOpacity
onPress={()=>navigation.navigate("Home")}
>
<Image source={{uri:"https://cdn-icons-png.flaticon.com/128/189/189254.png"}} style={{width:30,height:30,marginLeft:10,marginTop:20}}/>
<Text style={{fontSize:30 ,color:'white',textAlign:'center',fontWeight:'bold',marginTop:-40}}> hello world</Text>
</TouchableOpacity>
</ImageBackground>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: false,
}}>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
image: {
width: "100%",
height: 60,
},
text: {
color: 'white',
fontSize: 42,
lineHeight: 84,
fontWeight: 'bold',
backgroundColor: '#000000c0',
},
});
export default App;

React-navigation stack horizontal screen gesture for Android. (react-navigation/stack)

On Android, I am aware that the stack screen animation can be controlled to be horizontal when using the react-navigation-stack library with the transitionConfig prop. However, it doesn't seem to work for the react-navigation/stack library, or rather it doesn't have any support for it. Have anyone managed to make it work with react-navigation/stack? Or are there any way to combine both libraries, as i would find it a waste to rewrite my codes in another library just for this small issue. Any help would be appreciated!
Use it like this -
Working Example
Youtube Tutorial for Navigation Gestures
import * as React from 'react';
import { Button, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { Easing } from 'react-native';
import {
createStackNavigator,
CardStyleInterpolators,
} from '#react-navigation/stack';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Go to Profile"
onPress={() => navigation.navigate('Profile')}
/>
</View>
);
}
function ProfileScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Go to Notifications"
onPress={() => navigation.navigate('Notifications')}
/>
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
const Stack = createStackNavigator();
const timingConfig = {
animation: 'timing',
config: {
duration: 200,
easing: Easing.linear,
},
};
const options = {
gestureEnabled: true,
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
transitionSpec: {
open: timingConfig,
close: timingConfig,
},
};
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} options={options} />
<Stack.Screen
name="Notifications"
component={NotificationsScreen}
options={options}
/>
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={options}
/>
<Stack.Screen
name="Settings"
component={SettingsScreen}
options={options}
/>
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}

How can I place an icon before Home and Notifications of the Drawer.Screen

I am learning how to use React Navigation.
How can I place an icon before Home and Notifications of the Drawer.Screen
import * as React from 'react';
import { Button, View } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => navigation.navigate('Notifications')}
title="Go to notifications"
/>
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
And how do I do so that when entering the view add a tab screen
You can create a custom component and render it in your drawer.
Here the ButtonList is a custom component that you pass it to drawerContent. And you can create a list in the ButtonList and put the icon between Home and Notification easily.
<ActionDrawer.Navigator
drawerType="back"
drawerPosition="right"
drawerContent={(props) => <ButtonList {...props} />}
drawerStyle={{
width: wp('65'),
}}
>

How to always Show Bottom Tabs Label in React Native Navigation V5?

return (
<Tab.Navigator
barStyle={{backgroundColor: '#F2F2F2'}}
initialRouteName="Catalog">
<Tab.Screen
name="Settings"
options={{
tabBarLabel: 'Alterações',
title: 'Configurações',
tabBarIcon: ({color}) => (
<MaterialCommunityIcons name="cog" color="#000" size={22} />
),
}}>
{(props) => (
<Settings
{...props}
params={{
cpf: params.cpf ? params.cpf : cpf,
}}
/>
)}
</Tab.Screen>
<Tab.Screen
name="Catalog"
options={{
tabBarVisible: false,
title: 'Ofertas',
}}>
{(props) => (
<Catalog
{...props}
params={{
pracaId: params.pracaId ? params.pracaId : pracaId,
}}
/>
)}
</Tab.Screen>
[...]
</Tab.Navigator>
);
The documentations says to use the titleDisplayMode but where? when? I only find solution for older versions. I need it to v5.
Please, can some one help me?
I have include some part of my code to understend how I'm using the lib
There is a shifting prop that you can put to false in your navigator :
<Tab.Navigator
barStyle={{backgroundColor: '#F2F2F2'}}
initialRouteName="Catalog"
shifting={false}
>
.....
Whether the shifting style is used, the active tab icon shifts up to show the label and the inactive tabs won't have a label.
By default, this is true when you have more than 3 tabs. Pass shifting={false} to explicitly disable this animation, or shifting={true} to always use this animation.
https://reactnavigation.org/docs/5.x/material-bottom-tab-navigator#shifting
I have created this example where the HomeScreen always hide the bottom tab and the SettingsStack always show the bottom tab automatically. The key point is basically these lines of code, one have just a screen and the other one have a StackNavigator:
<Tab.Screen name="HomeScreen" component={HomeScreen} />
<Tab.Screen name="SettingsStack" component={SettingsStack} />
This example is similar to the one in the docs https://reactnavigation.org/docs/hiding-tabbar-in-screens/, but with more components.
The code below is in snack, check if this helps you:
https://snack.expo.io/#ronicesarrc/react-navigation-hiding-showing-bottom-tab-navigator
import React from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
function SettingsInternalScreen() {
return (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'orange',
}}>
<Text>SettingsInternalScreen!</Text>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'red',
}}>
<TouchableOpacity
style={{ backgroundColor: 'orange', padding: 16 }}
onPress={() => navigation.navigate('SettingsInternalScreen')}>
<Text>Go to Screen showing bottom tab</Text>
</TouchableOpacity>
</View>
);
}
const SettingStack = createStackNavigator();
function SettingsStack() {
return (
<SettingStack.Navigator>
<SettingStack.Screen name="SettingsScreen" component={SettingsScreen} />
<SettingStack.Screen
name="SettingsInternalScreen"
component={SettingsInternalScreen}
/>
</SettingStack.Navigator>
);
}
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity
style={{ backgroundColor: 'gray', padding: 16 }}
onPress={() => navigation.navigate('HomeInternalScreen')}>
<Text>Go to Screen hidding bottom tab</Text>
</TouchableOpacity>
</View>
);
}
function HomeInternalScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>HomeInternalScreen!</Text>
</View>
);
}
const Tab = createMaterialBottomTabNavigator();
const Tabs: React.FC = () => {
return (
<Tab.Navigator>
<Tab.Screen name="HomeScreen" component={HomeScreen} />
<Tab.Screen name="SettingsStack" component={SettingsStack} />
</Tab.Navigator>
);
};
const MainStack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<MainStack.Navigator headerMode="none">
<MainStack.Screen name={'Tabs'} component={Tabs} />
<MainStack.Screen
name={"HomeInternalScreen"}
component={HomeInternalScreen}
/>
</MainStack.Navigator>
</NavigationContainer>
);
}