I would like to change the styling of a main button. Although this code is not working. I would like the styling to not be affected by the nav bar height. Here is code
const CircleButton = ({ children, onPress }) => (
<TouchableOpacity onPress={onPress} style={{
top: -30,
justifyContent: 'center',
alignItems: 'center',
...style.shadow
}}>
<View style={{
width: 70,
height: 70,
borderRadius: 35,
backgroundColor: 'yellow',
}}>
{children}
</View>
</TouchableOpacity>
)
<bTabs.Navigator
screenOptions={{ tabBarLabel: false, }}
barStyle={{
position: 'absolute',
bottom: 25,
left: 20,
right: 20,
elevation: 0,
backgroundColor: theme.nav.backgroundColor,
borderRadius: 10,
height: 50,
...style.shadow
}}
>
<bTabs.Screen name="Create" component={CreateContent} options=
{{
tabBarIcon: ({ focused }) => (
<View>
<Icon name='plus' size={25} color={focused ? theme.mainColor : theme.secondaryBGColor} />
</View>
),
tabBarButton: (...props) => <CircleButton {...props} onPress={() => console.log('t')} />,
}}
/>
Also note i have tried using tabBarButton: (...props) => (<CircleButton {...props} onPress={() => console.log('t')} />), and with {}
Please ignore syntax. Thank you
Related
I have a bottom tab navigator that works well.
It calls differents screens when pressing the buttons.
What I need to do is to call a screen from a component when I close it by pressing a button.
To add more details, consider that I have two screens (home and messenger).
When I am on the messenger screen, I open a component by pressing a button.
This component takes all the screen. When I close it, I would like to be "redirected" to the home screen directly, not the messenger one.
I work on Expo.
How can I achieve that ?
The navigator code :
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import { Text, View, Image } from "react-native";
import News from "../screens/News";
import Explorer from "../screens/Explorer";
import Home from "../screens/Home";
import Scanner from "../screens/Scanner";
import Search from "../screens/Search";
import Publish from "../screens/Publish";
import Write from "../screens/Write";
import Messenger from "../screens/Messenger";
import { RFPercentage } from "react-native-responsive-fontsize";
import { DataContext } from "../components/Context";
import { useState, useContext, useEffect } from "react";
const Tab = createBottomTabNavigator();
export default function Tabs() {
const {
login,
screenName,
openRecharge,
openCollect,
openAskCash,
openTransfer,
openConvert,
menuPage,
notifModal,
} = useContext(DataContext);
console.log(login);
return (
<Tab.Navigator
screenOptions={({ route }) => ({
headerShown: false,
tabBarShowLabel: true,
tabBarHideOnKeyboard: true,
tabBarStyle: {
display:
login != 1 ||
openRecharge ||
openCollect ||
openAskCash ||
openConvert ||
openTransfer ||
notifModal ||
menuPage == "index" ||
menuPage == "profile"
? "none"
: "flex",
backgroundColor: "#FFFFFF",
height: "8%",
position: "absolute",
borderTopColor: "transparent",
elevation: login != 1 ? 0 : 20,
},
})}
>
<Tab.Screen
name="Home"
component={Home}
options={{
unmountOnBlur: true,
tabBarLabel: ({ focused }) => (
<Text
style={{
color: focused ? "#373945" : "#75787d",
fontFamily: "Jost",
fontWeight: "700",
fontSize: RFPercentage(1.2),
marginTop: -10,
marginBottom: 10,
}}
>
ACCUEIL
</Text>
),
tabBarIcon: ({ focused }) =>
focused ? (
<Image
source={require("../assets/home-active.png")}
style={{ width: 20, height: 20 }}
/>
) : (
<Image
source={require("../assets/home.png")}
style={{ width: 20, height: 20 }}
/>
),
}}
/>
<Tab.Screen
name="Explorer"
component={Explorer}
options={{
unmountOnBlur: true,
tabBarLabel: ({ focused }) => (
<Text
style={{
color: focused ? "#373945" : "#75787d",
fontFamily: "Jost",
fontWeight: "700",
fontSize: RFPercentage(1.2),
marginTop: -10,
marginBottom: 10,
}}
>
MARCHÉS
</Text>
),
tabBarIcon: ({ focused }) =>
focused ? (
<Image
source={require("../assets/explorer-active.png")}
style={{ width: 20, height: 20 }}
/>
) : (
<Image
source={require("../assets/explorer.png")}
style={{ width: 20, height: 20 }}
/>
),
}}
/>
{(() => {
switch (screenName) {
case "Home":
return (
<Tab.Screen
name="Scanner"
component={Scanner}
options={{
unmountOnBlur: true,
tabBarLabel: ({ focused }) => (
<Text
style={{
color: "#ffffff",
}}
>
SCANNER
</Text>
),
tabBarIcon: ({ focused }) => (
<View
style={{
width: 55,
height: 55,
backgroundColor: "#089baa",
borderRadius: 50,
marginBottom: 30,
justifyContent: "center",
alignItems: "center",
}}
>
<Image
source={require("../assets/scanner-blanc.png")}
style={{ width: 28, height: 28 }}
/>
</View>
),
}}
/>
);
case "Explorer":
return (
<Tab.Screen
name="Search"
component={Search}
options={{
unmountOnBlur: true,
tabBarLabel: ({ focused }) => (
<Text
style={{
color: "#ffffff",
}}
>
SEARCH
</Text>
),
tabBarIcon: ({ focused }) => (
<View
style={{
width: 55,
height: 55,
backgroundColor: "#089baa",
borderRadius: 50,
marginBottom: 30,
justifyContent: "center",
alignItems: "center",
}}
>
<Image
source={require("../assets/glass-white.png")}
style={{ width: 28, height: 28 }}
/>
</View>
),
}}
/>
);
case "News":
return (
<Tab.Screen
name="Publish"
component={Publish}
options={{
unmountOnBlur: true,
tabBarLabel: ({ focused }) => (
<Text
style={{
color: "#ffffff",
}}
>
PUBLISH
</Text>
),
tabBarIcon: ({ focused }) => (
<View
style={{
width: 55,
height: 55,
backgroundColor: "#089baa",
borderRadius: 50,
marginBottom: 30,
justifyContent: "center",
alignItems: "center",
}}
>
<Image
source={require("../assets/add.png")}
style={{ width: 28, height: 28 }}
/>
</View>
),
}}
/>
);
case "Messenger":
return (
<Tab.Screen
name="Write"
component={Write}
options={{
unmountOnBlur: true,
tabBarLabel: ({ focused }) => (
<Text
style={{
color: "#ffffff",
}}
>
MESSENGER
</Text>
),
tabBarIcon: ({ focused }) => (
<View
style={{
width: 55,
height: 55,
backgroundColor: "#089baa",
borderRadius: 50,
marginBottom: 30,
justifyContent: "center",
alignItems: "center",
}}
>
<Image
source={require("../assets/pencil.png")}
style={{ width: 28, height: 28 }}
/>
</View>
),
}}
/>
);
default:
return null;
}
})()}
<Tab.Screen
name="News"
component={News}
options={{
unmountOnBlur: true,
tabBarLabel: ({ focused }) => (
<Text
style={{
color: focused ? "#373945" : "#75787d",
fontFamily: "Jost",
fontWeight: "700",
fontSize: RFPercentage(1.2),
marginTop: -10,
marginBottom: 10,
}}
>
FIL D'ACTUS
</Text>
),
tabBarIcon: ({ focused }) =>
focused ? (
<Image
source={require("../assets/news-active.png")}
style={{ width: 20, height: 20 }}
/>
) : (
<Image
source={require("../assets/news.png")}
style={{ width: 20, height: 20 }}
/>
),
}}
/>
<Tab.Screen
name="Messenger"
component={Messenger}
options={{
unmountOnBlur: true,
tabBarLabel: ({ focused }) => (
<Text
style={{
color: focused ? "#373945" : "#75787d",
fontFamily: "Jost",
fontWeight: "700",
fontSize: RFPercentage(1.2),
marginTop: -10,
marginBottom: 10,
}}
>
MESSAGES
</Text>
),
tabBarIcon: ({ focused }) =>
focused ? (
<Image
source={require("../assets/messagerie-active.png")}
style={{ width: 20, height: 20 }}
/>
) : (
<Image
source={require("../assets/messagerie.png")}
style={{ width: 20, height: 20 }}
/>
),
}}
/>
</Tab.Navigator>
);
}
I faced the same issue before, this is how I solved it:
Created a global flag that changes to a specific value (example: 1) when I go to the target screen, in your case the Component which takes the whole screen
I perform a check in the Messenger screen in a useFocusEffect hook that if the flag is 1 redirect to the home screen and change the flag to 0
This way I can visit the Messenger screen again cause the value will be 0 but once I open the component it will change to 1 and once I press back I will be redirected to Home Screen
The useFocusEffect part:
import { useFocusEffect } from "#react-navigation/native";
export default function ConfirmOrder(){
useFocusEffect(
React.useCallback(() => {
if (cart.length == 0) {
navigation.navigate("Home");
}
})
);
return(
<Text>Confirm Order Page</Text>
)
}
If have the following code :
const Tab = createBottomTabNavigator();
export default function Tabs() {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
headerShown: false,
tabBarShowLabel: true,
tabBarHideOnKeyboard: true,
tabBarStyle: {
backgroundColor: "#FFFFFF",
height: "8%",
position: "absolute",
},
})}
>
<Tab.Screen
name="Home"
component={Home}
options={{
tabBarLabel: ({ focused }) => (
<Text
style={{
color: focused ? "#299ca4" : "#b5b5b5",
fontFamily: "Jost",
fontWeight: "600",
fontSize: RFPercentage(1.2),
marginTop: -10,
marginBottom: 10,
}}
>
ACCUEIL
</Text>
),
tabBarIcon: ({ focused }) =>
focused ? (
<Image
source={require("../assets/home-active.png")}
style={{ width: 20, height: 20 }}
/>
) : (
<Image
source={require("../assets/home.png")}
style={{ width: 20, height: 20 }}
/>
),
}}
/>
<Tab.Screen
name="Explorer"
component={Explorer}
options={{
tabBarLabel: ({ focused }) => (
<Text
style={{
color: focused ? "#299ca4" : "#b5b5b5",
fontFamily: "Jost",
fontWeight: "600",
fontSize: RFPercentage(1.2),
marginTop: -10,
marginBottom: 10,
}}
>
MARCHES
</Text>
),
tabBarIcon: ({ focused }) =>
focused ? (
<Image
source={require("../assets/explorer-active.png")}
style={{ width: 20, height: 20 }}
/>
) : (
<Image
source={require("../assets/explorer.png")}
style={{ width: 20, height: 20 }}
/>
),
}}
/>
<Tab.Screen
name="Scanner"
component={Scanner}
options={{
tabBarLabel: ({ focused }) => (
<Text
style={{
color: "#ffffff",
}}
>
SCANNER
</Text>
),
tabBarIcon: ({ focused }) => (
<View
style={{
width: 55,
height: 55,
backgroundColor: "#089baa",
borderRadius: 50,
marginBottom: 30,
justifyContent: "center",
alignItems: "center",
}}
>
<Image
source={require("../assets/scanner-blanc.png")}
style={{ width: 28, height: 28 }}
/>
</View>
),
}}
/>
<Tab.Screen
name="Community"
component={Community}
options={{
tabBarLabel: ({ focused }) => (
<Text
style={{
color: focused ? "#299ca4" : "#b5b5b5",
fontFamily: "Jost",
fontWeight: "600",
fontSize: RFPercentage(1.2),
marginTop: -10,
marginBottom: 10,
}}
>
FIL D'ACTU
</Text>
),
tabBarIcon: ({ focused }) =>
focused ? (
<Image
source={require("../assets/news-active.png")}
style={{ width: 20, height: 20 }}
/>
) : (
<Image
source={require("../assets/news.png")}
style={{ width: 20, height: 20 }}
/>
),
}}
/>
<Tab.Screen
name="Profile"
component={Menu}
options={{
unmountOnBlur: true,
tabBarLabel: ({ focused }) => (
<Text
style={{
color: focused ? "#299ca4" : "#b5b5b5",
fontFamily: "Jost",
fontWeight: "600",
fontSize: RFPercentage(1.2),
marginTop: -10,
marginBottom: 10,
}}
>
PROFIL
</Text>
),
tabBarIcon: ({ focused }) =>
focused ? (
<Image
source={require("../assets/profile-active.png")}
style={{ width: 20, height: 20 }}
/>
) : (
<Image
source={require("../assets/profile.png")}
style={{ width: 20, height: 20 }}
/>
),
}}
/>
</Tab.Navigator>
);
}
If I am on any screen, the "Scanner" button in the center of the navigator displays the "Scanner" screen when pressed.
What I need to do is to render another button to display another view instead of it, if I am on a different screen.
For instance, if I am in the "Home" screen, I want the "Scanner" button, and if I am in the "Explorer" screen, I want the "Scanner" button be replaced with another one to call another screen.
I have a drawer navigation where I am trying to put a footer on the bottom which would contain additional info (app version and logout link) ..
This is my navigation container:
<NavigationContainer style={styles.drawer}>
<Drawer.Navigator style={styles.drawer} drawerContent={props => <CustomDrawerContent {...props} />}>
<Drawer.Screen name="Home" component={Home}
options={{
drawerIcon: ({ focused, size }) => (
<Image source={require('./assets/icons/sidemenu-icon-account.png')} style={[{ height: 25, width: 25 }]} />
)
}} />
<Drawer.Screen name="LoginScreen" component={LoginScreen}
options={{
drawerIcon: ({ focused, size }) => (
<Image source={require('./assets/icons/sidemenu-icon-account.png')} style={[{ height: 25, width: 25 }]} />
)
}} />
</Drawer.Navigator>
</NavigationContainer>);
And this is the custom content:
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView style={styles.drawer} {...props}>
<View style={styles.logoContainer}>
<Image source={require("./assets/logo.png")} style={{ height: "100%", width: "100%", resizeMode: "contain" }} />
</View>
<SafeAreaView style={styles.container}>
<View style={{flex: 1 }}>
<DrawerItemList {...props} />
</View>
<TouchableOpacity style={{backgroundColor: 'red', flexDirection: 'row', alignItems: 'center'}}>
<Text>Log Out</Text>
</TouchableOpacity>
</SafeAreaView>
</DrawerContentScrollView>
);
}
How can I push the log out link to be fixed at the bottom?
Styles:
const styles = StyleSheet.create({
img: {
height: 40,
width: 40,
marginTop: 6,
justifyContent: 'center',
textAlignVertical: 'center',
},
logout : {
backgroundColor: 'red' ,
bottom: 0,
position: 'absolute'
},
logoContainer: {
height: 140,
width: "80%",
marginTop: 20,
marginBottom: 20,
alignSelf: "center",
},
drawer: {
backgroundColor: 'yellow',
flex:1
},
labelBottom : {
position: 'relative',
bottom:0
},
redBottom: {
},
scrollView: {
backgroundColor: Colors.lighter,
},
engine: {
position: 'absolute',
right: 0,
},
body: {
backgroundColor: Colors.red,
},
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
color: Colors.black,
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
color: Colors.dark,
},
highlight: {
fontWeight: '700',
},
footer: {
color: Colors.dark,
fontSize: 12,
fontWeight: '600',
padding: 4,
paddingRight: 12,
textAlign: 'right',
},
Instead of style prop, you may use contentContainerStyle:
<DrawerContentScrollView
...
contentContainerStyle={styles.drawerContentContainer}
/>
while the style is something like:
drawerContentContainer: {justifyContent: 'space-between', flex: 1},
You can use a marginTop: 'auto' style for TouchableOpacity, also use the contentContainerStyle for scrollviews
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView contentContainerStyle={styles.drawer} {...props}>
<View style={styles.logoContainer}>
<Image source={require("./assets/logo.png")} style={{ height: "100%", width: "100%", resizeMode: "contain" }} />
</View>
<SafeAreaView style={{flex:1}}>
<View>
<DrawerItemList {...props} />
</View>
<View style={{ marginTop: 'auto' }}>
<TouchableOpacity
style={{
backgroundColor: 'red',
flexDirection: 'row',
}}>
<Text>Log Out</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
</DrawerContentScrollView>
);
}
I solved this by wrapping all the contents of my DrawerComponent inside a View element and then adding height: '100%' in the style prop of the root View element.
And finally adding marginTop: 'auto' will push the FooterComponent at the bottom (or you can use {position: 'absolute', bottom: 0} for style prop of FooterComponent).
<View style={{height: '100%'}}>
<HeaderComponent />
<DrawerItems {...props} />
<View style={{marginTop: 'auto'}}>
<FooterComponent />
</View>
</View>
I want to update or show the badge count in bottom tabs, how can I pass count from API in Component to Tab.Navigator and display the count in the bottom tabs.
sample code
`import Channels from '#channels';
import Documents from '#documents';
render(){
return(
<Tab.Navigator
initialRouteName={this.state.selectedTab}
tabBarOptions={{
activeTintColor: '#248E42',
labelStyle:{fontSize:width/35'}
}}
>
<Tab.Screen
name="Channels"
component={Channels}
options={{
tabBarLabel: 'Channels',
tabBarIcon: ({ focused,badgeCount }) => (
<View>
<Image source={Images.iconChannel} style={{ height: 24, width: 24 }} />
{badgeCount < 0 &&
(
<View style={styles.badge}>
<Text style={{ color: 'white', fontSize: 10, fontWeight: 'bold' }}>{badgeCount}</Text>
</View>
)
}
</View>
)
}}
/>
<Tab.Screen
name="Documents"
component={Documents}
options={{
tabBarLabel: 'Documents',
tabBarIcon: ({ focused }) => (
<Image source={Images.iconDocuments} style={{ height: 24, width: 24 }} />
),
}}
/>
</Tab.Navigator>)}
`
Your Environment
`#react-navigation/native - ^5.1.7
#react-navigation/bottom-tabs - ^5.2.8
react-native-screens - ^2.7.0
react-native - 0.62.2`
I was also having this problem for my notifications badge in bottom tabs. So, I made tabbarIcon a separate component and connected it with app state.
class BottomTabIcon extends Component {
render() {
const { color, notifications: { data: notifications } } = this.props;
const badgeCount = _.filter(notifications, notification => !notification.is_read).length;
return (
<View style={{ width: 24, height: 24, margin: 5 }}>
<Image source={images.bottom_notification} style={{ tintColor: color }} />
<View
style={{
position: 'absolute',
right: -6,
top: -3,
backgroundColor: 'red',
padding: 3,
borderRadius: 6,
// width: 12,
// height: 12,
justifyContent: 'center',
alignItems: 'center',
}}
>
<Text style={{ color: 'white', fontSize: 10, fontWeight: 'bold' }}>
{badgeCount}
</Text>
</View>
</View>
);
}
}
const mapStateToProps = state => ({
notifications: state.notifications
})
export default connect(mapStateToProps)(BottomTabIcon);
Then Imported the component to use as tabbarIcon.
<Tab.Navigator
initialRouteName={this.state.selectedTab}
tabBarOptions={{
activeTintColor: '#248E42',
labelStyle:{fontSize:width/35'}
}}
>
<Tab.Screen
name="Channels"
component={Channels}
options={{
tabBarLabel: 'Channels',
tabBarIcon: (props) => <BottomTabIcon {...props} />
)
}}
/>
</Tab.Navigator>
This solution worked for me, I hope this solves your problem also
I connected the whole TabNavigator and passed the needed properties.
I am trying to create parallax with tab screen. This is the screen that I have created:
In this screen the tab scroll upward before completing the list but I want that the tabs scroll after the list in tabs completed Here is the code:
<Tabs
prerenderingSiblingsNumber={3}
onChangeTab={({ i }) => {
this.setState({ height: this.heights[i], activeTab: i });
}}
renderTabBar={props => (
<Animated.View
style={[
{
zIndex: 1,
width: "100%",
backgroundColor: '#fff'
},
Platform.OS === "ios" ? { paddingTop: 20 } : null
]}
>
<ScrollableTab
{...props}
renderTab={(name, page, active, onPress, onLayout) => (
<TouchableOpacity
key={page}
onPress={() => onPress(page)}
onLayout={onLayout}
activeOpacity={0.4}
>
<Animated.View
style={{
flex: 1,
height: 100,
backgroundColor: 'grey'
}}
>
<TabHeading
scrollable
style={{
backgroundColor: "transparent",
width: SCREEN_WIDTH / 3
}}
active={active}
>
<Animated.Text
style={{
fontWeight: active ? "bold" : "normal",
color: 'black',
fontSize: 14
}}
>
{name}
</Animated.Text>
</TabHeading>
</Animated.View>
</TouchableOpacity>
)}
underlineStyle={{ backgroundColor: this.textColor }}
/>
</Animated.View>
)}
>