How to put an image in a react-native drawer? - react-native

I am using the #react-navigation/native library. I have a drawer with some screens in them. I can click on the links and navigate to the appropriate screen. I would like to place an image above the links in the drawer. I am using the property drawerContent to do this. However, when I do this it removes the links. I cant figure out how to have the links and the image above the links in the drawer. What is the correct way to do this? Here is some code for my drawer with the drawerContent.
<NavigationContainer>
<Drawer.Navigator
initialRouteName="Screen1"
drawerContent={() => (
<View style={{height: "10%"}}>
<Image
style={{width: "90%"}}
resizeMode="contain"
source={require('../../../assets/new-logo/textSide.png')}/>
</View>
)}
screenOptions={ ({navigation}) => ({
drawerContainerStyle: {paddingTop: 100},
drawerLabelStyle: {
fontSize: KbStyles.properties.drawerLabelSize,
color: "white"
},
headerTintColor: {color: KbStyles.properties.white},
headerStyle: {
backgroundColor: KbStyles.properties.black
},
headerTitleStyle: {
fontSize: KbStyles.properties.headerSize,
color: "white"
},
headerLeft: () => (
<TouchableWithoutFeedback
onPress={() => {navigation.toggleDrawer()}}>
<Image
resizeMode="contain"
style={{height: "50%"}}
source={require("../../../assets/menu.png")}
/>
</TouchableWithoutFeedback>
),
drawerActiveBackgroundColor : KbStyles.properties.red,
drawerActiveTintColor: KbStyles.properties.white,
drawerStyle: {
backgroundColor: "black",
width: 300
}
})}
>
<Drawer.Screen name="Screen1" component={Screen1} />
<Drawer.Screen name="Screen2 component={Screen2} />
<Drawer.Screen name="Screen3" component={Screen3} />
</Drawer.Navigator>
</NavigationContainer>
Here is also an image showing what I would like to achieve.
What is the correct way to do this?

You can try this
Under the Drawer.Navigator you can use drawerContent as,
drawerContent={(props)=> {
return(
<View style={{flex:1}}>
<DrawerContentScrollView {...props}>
<ImageBackground source={require("../Assets/Vrda1img2.jpg")} style={{justifyContent:"space-between",alignItems:"center",padding:20,marginBottom:20,backgroundColor:"rgb(0,0,0)",borderBottomWidth:2,borderColor:Colors.secondary}} imageStyle=
{{opacity:0.4}}>
<Image source={require("../Assets/vector.png")} style={{width:70,height:70,borderRadius:35,borderWidth:2,borderColor:Colors.white}}/>
<Text style={{fontSize:20,fontWeight:"bold",color:Colors.white}}>{userDetail?userDetail.name:"Not Available"}</Text>
<Text style={{color:Colors.light}}>{userDetail?userDetail.email:"Not Available"}</Text>
</ImageBackground>
<DrawerItemList {...props}/>
</DrawerContentScrollView>
<TouchableOpacity onPress={()=>{logout()}} style={{position:"relative",right:0,left:0,bottom:5,backgroundColor:"rgb(231,230,230)"}}>
<Text style={{backgroundColor:"rgba(162,160,160,0.29)",width:"100%",height:40,textAlign:"center",paddingTop:8}}><SimpleLineIcons name={"logout"} size={15} color={Colors.primary}/> LogOut</Text>
</TouchableOpacity>
</View>
)
}
}
I give you the reference of my code where you can add Image under the Image background you can also use Uri to add an image as a link.

Related

How can I have a custom navigation component in react-native-navigation Stack?

I'm trying:
export default function Navigator() {
return (<>
<Stack.Navigator screenOptions={{
headerShown: false
}} initialRouteName="Home" >
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Feed" component={FeedScreen} />
</Stack.Navigator >
<CustomTabBar />
</>
);
}
And:
export const CustomTabBar = () => {
const onHomePress = () => { }
return (
<SafeAreaView style={styles.safeAreaView}>
<View style={styles.navContainer}>
<View style={{ flex: 1 }}>
<Avatar rounded source={{ uri: 'https://source.unsplash.com/random/100x100?profile picture,smile' }} containerStyle={styles.avatar} />
</View>
<View style={{ flex: 1 }}>
<Chip
title={<View style={styles.pillContainer}>
<Ionicons name='search' color='white' />
<TouchableOpacity onPress={onHomePress}>
<Ionicons name='ios-home' color='white' />
</TouchableOpacity>
<Ionicons name='planet' color='white' />
</View>}
type="outline"
containerStyle={styles.chipContainer}
/>
</View>
<View style={{ flex: 1 }}>
<Animated.View style={styles.btnCircle}>
<TouchableOpacity
style={{
flex: 1,
justifyContent: 'center'
}}
onPress={() => Alert.alert('Click Action')}>
<Ionicons name={'paper-plane-outline'} color={'white'} size={25} />
</TouchableOpacity>
</Animated.View>
</View>
</View>
</SafeAreaView>
);
}
If I move the CustomTabBar inside the Stack.Navigator, we get an error.
but this creates the white area at the bottom:
How can I have my custom navigation element?
StackScreen at custom bottom tab bar is not bad idea.
If you want custom bottom tab bar for use custom tabbar, actually still you can use BottomTabBar but if you want use stack screens, try like this.
<>
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name={"TestScreen"} component={TestScreen} />
</Stack.Navigator>
</NavigationContainer>
{/* custom tab bar */}
<View
style={{
position: "absolute",
bottom: 0,
width: "100%",
alignItems: "center",
}}>
<Text>TEST</Text>
<Text>TEST</Text>
<Text>TEST</Text>
<Text>TEST</Text>
</View>
</>
In your case, White Space is'nt custom tab bar's background. And stack screen's height is not "100%".
So In case, you can use position: "absolute", bottom: 0 then screen get full area, and cover the deault background(whitespace).

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>

how to nest navigation with react native?

here is my AppNavigator.js
const StackNavigator = createStackNavigator(
{
LoginScreen: LoginScreen,
RegisterScreen: RegisterScreen,
Tabs:Tabs,
Detail:DetailScreen
},
{
initialRouteName: 'LoginScreen',
headerMode: 'none',
});
export default createAppContainer(StackNavigator)
here is my Tabs.js
<Tab.Navigator
tabBarOptions={{
showLabel: false,
style:{
position: 'absolute',
bottom:5,
left:5,
right:5,
elevation:0,
backgroundColor: '#068b71',
borderRadius:10,
height: 50,
...styles.shadow
}
}}>
<Tab.Screen name="Home" component={HomeScreen}
options={{
tabBarIcon:({focused})=>(
<View style={{alignItems:'center', justifyContent:'center'}}>
<Image source={require('../assets/icons/home.png')}
resizeMode='contain'
style={{
width:25,
height:25,
tintColor: focused ? '#ffffff' : '#748c94'
}}/>
<Text style={{color: focused ? '#ffffff' : '#748c94', fontSize:10}}>Home</Text>
</View>
)
}} >
</Tab.Screen>
<Tab.Screen name="Profile" component={ProfileScreen}
options={{
tabBarIcon:({focused})=>(
<View style={{alignItems:'center', justifyContent:'center'}}>
<Image source={require('../assets/icons/profile.png')}
resizeMode='contain'
style={{
width:25,
height:25,
tintColor: focused ? '#ffffff' : '#748c94'
}}/>
<Text style={{color: focused ? '#ffffff' : '#748c94', fontSize:10}}>Profile</Text>
</View>
)
}} />
</Tab.Navigator>
and i want to navigate from list view that exist in homeScreen
<TouchableOpacity style={styles.item} onPress={()=>{navigation.navigate('Detail')}}>
i got this error :
The action 'NAVIGATE' with payload {"name":"Detail"} was not handled by any navigator.
itry many solution but none of them work help please im stuck.
here you can you like this may be this will help you
<TouchableOpacity style={styles.item} onPress={()=>navigation.navigate('DetailScreen')}>

Customize header in react native navigation

in my app home screen I want to custom the header to have two icons in left and right which can be done using:
<HomeStack.Screen
name="Home"
component={HomeScreen}
options={{
title: '',
headerLeft: () => (
<View style={{ marginLeft: 10 }}>
<Icon.Button
name="ios-menu"
size={25}
color="#000000"
backgroundColor={COLORS.primary}
onPress={() => navigation.openDrawer()}
/>
</View>
),
headerRight: () => (
<View style={{ marginLeft: 10 }}>
<Icon.Button
name="location-outline"
size={25}
color="#000000"
backgroundColor={COLORS.primary}
onPress={() => navigation.openMap()}
/>
</View>
),
}} />
</HomeStack.Navigator>
I want to add additional but to be in the center which will be customized based on my needs, but I have no idea how to implement that as there is nothing called headerCneter:
Perhaps you can take advantage of the header option inside the stack navigator? You can then use the route params to customize your header from there.
You can pass react component in headerTitle:
<HomeStack.Screen
name="Home"
component={HomeScreen}
options={{
headerTitle: () => {
return (
<View style={st.horizontalRow}>
<LeftIcon />
<TextInput
placeholder="search"
/>
<RightIcon />
</View>
);
},
headerTitleAlign: 'left',
headerTitleContainerStyle: {
left: 40,
right: 0,
},
}} />

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>