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

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

Related

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

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.

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>

React Native Drawer Item I want to set icon right side via

Please check screenshot
1 - Screenshot of Code
2 - Screenshot of Sidemenu
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
padding: 12,
color: 'white',
borderBottomWidth: 1,
borderBottomColor: '#aaaaaa',
backgroundColor:
global.currentScreenIndex === item.screenToNavigate
? '#c1c0c0'
: '#fff',
}}
key={key}
onStartShouldSetResponder={() =>
handleClick(key, item.screenToNavigate)
}>
{/* <View style={{ marginRight: 5, marginLeft: 10 }}>
<Icon name={item.navOptionThumb} size={25} color="#273983" />
</View> */}
<Text style={{ fontSize: 17, color: 'black', marginLeft: 10,}}>
{item.navOptionName}
</Text>
<View style={{ marginRight:5}}>
{/* <Icon name={item.navOptionThumb} size={25} color="#808080" /> */}
<Icon name={item.navOptionThumb} size={20} color="#273983" />
</View>
</View>
try this its worked for me (react navigation v6)
<DrawerNavigator.Screen
name="Home"
options={{
drawerIcon: ({color}) => (
<Icon name="md-home" color={color}
style={{ position: "absolute",right: 10,}}
/>
)
}}
/>
Use drawerLabel property
const SyncIconFunc = {
drawerLabel: config=>
<View style={{flexDirection:'row'}}>
<Text style={{color:Colors.bg}}>
Sync Data
</Text>
<Feather
onPress={() => alert("bell pressed")}
style={{ position:'absolute',right: 10}}
size={24}
color={Colors.bg}
name="bell"
/>
</View>
};
<Drawer.Navigator>
<Drawer.Screen name="Catalogues" component={FolderList}/>
<Drawer.Screen name="Sync Data" component={SyncData} options={SyncIconFunc}/>
<Drawer.Screen name="Notifications" component={FolderList}/>
</Drawer.Navigator>

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>

Sliding Tabbar Highlight React Native

Attempting to replicate the following but for a bottom tabbar (moving an underlying blue line that follows the user selection underneath the tabbar):
https://raw.githubusercontent.com/brentvatne/react-native-scrollable-tab-view/master/demo.gif
Here is what I have so far (but the red underline doesn't slide and is static based on the user's selection):
So far here is my code:
return <Tabbar
selected={this.state.selected}
tabHeight={window.height/16}
style={styles.menu}
onTabItemPress={name => this.setState({ selected: name })}
renderTabComponent
renderTabComponent={(name, isActive) => (
<View
style={[
{ borderBottomWidth: 2, justifyContent: 'center', alignItems: 'center' },
isActive ? { borderColor: '#DB202A'} : { borderColor: 'transparent' }
]}>
<Text style={styles.menuText}>{ name }</Text>
</View>
)}>
<Tabbar.Item name="Causes" >
<Text>This is the Causes tab</Text>
</Tabbar.Item>
<Tabbar.Item name="Trending" >
<Text>This is the Trending tab</Text>
</Tabbar.Item>
<Tabbar.Item
name="Home" >
<View style={styles.containerSuper}>
<View style={styles.container}>
{this.renderListView()}
</View>
</View>
</Tabbar.Item>
<Tabbar.Item name="Profile" >
<Text>This is the Profile tab</Text>
</Tabbar.Item>
<Tabbar.Item name="Settings" >
<Text>This is the Settings tab</Text>
</Tabbar.Item>
</Tabbar>