React native v6: tab bar customization - react-native

i have a bottom tab in my react native application, when i try to edit the tabBarStyle on the tab navigator it doesnt work. It only works on 1 out of my 3 tabs for some reason.
Only the help tab follows the required design the home and the test tab remain as default. I have tried all solutions only add made sure that i am using screenOptions and tabBarStyle instead of style.
const Tab = createBottomTabNavigator();
const AppNavigator = () => {
return (
<Tab.Navigator
screenOptions={{
tabBarActiveTintColor:'white',
tabBarLabelStyle:{
fontWeight:'700'
},
tabBarStyle: {
backgroundColor:'black',
borderTopColor: 'black',
elevation: 0, // for Android
shadowOffset: {
width: 0, height: 0 // for iOS
},
height:Platform.OS==='ios'&& dimen.width>400?80:Platform.OS==='ios'&& dimen.width<400?60:50,
}
}}
initialRouteName={"Home"}
>
<Tab.Screen
name="Home"
component={HomeNavigator}
options={{
tabBarIcon: ({ size, color,focused }) => (
<Entypo name="home" size={30} color={'#969696'}/>
),
headerShown:false,
unmountOnBlur: true,
}}
/>
<Tab.Screen
name="Test"
component={TestNavigator}
options={({ navigation }) => ({
tabBarButton: () => (
<NewListingButton
onPress={() => navigation.navigate(routes.test)}
/>
),
tabBarIcon: ({ size, color }) => (
<FontAwesome
name="life-saver"
size={size}
color={color}
/>
),
headerShown: false,
unmountOnBlur: true,
})
}
/>
<Tab.Screen
name="Help"
component={HelpNavigator}
options={{
tabBarIcon: ({ size, color,focused }) => (
<Ionicons name="help" size={30} color={'#969696'}/>
),
unmountOnBlur: true,
headerShown:false,
}}
/>
</Tab.Navigator>
)
};
export default AppNavigator;

My problem was with react navigation 6 in order to hide the tab navigator on specific screens i had to set the tabBarStyle display to none, which was why the background wasnt changing if the tab had a stack

Related

React native reload bottom tabs on each click for webview

I have two bottom tabs 'Home' and 'Account' on the app and each one will load a webview of the website. When we click on the Home tab, it will load the website using the web view but if we go to the sub-items from that tab and then after clicking the Home tab again it doesn't change anything. I would like to go to the website's home page whenever a user clicks on the Home tab, Is it possible to do it? I tried using the unmountOnBlur: true option of the navigation and it's working if we are switching the different tabs but from the same tabs, it doesn't reload the page.
export default class App extends React.Component {
render() {
return (
<NavigationContainer>
<Tabs.Navigator
screenOptions={
{ headerShown: false }}
tabBarOptions={{
activeTintColor: '#000000',
inactiveTintColor: 'gray',
showLabel: false
}}
>
<Tabs.Screen name="Home" component={Home} options={{
unmountOnBlur: true,
tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
listeners={({ navigation }) => ({
tabPress: (e) => {
// Prevent default action
e.preventDefault();
navigation.navigate("Home");
},
})}/>
<Tabs.Screen name="Account" component={Account} options={{
unmountOnBlur: true,
tabBarLabel: 'Profile',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="account" color={color} size={size} />
),
}}
listeners={({ navigation }) => ({
tabPress: (e) => {
// Prevent default action
e.preventDefault();
navigation.navigate("Account");
},
})}/>
</Tabs.Navigator>
</NavigationContainer>
);
}
}

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

Stack nested inside Material Bottom Tab dont show the content when you navigate the second time (React Navigation v6)

Problem:
When I navigate to the Stack inside the Material Bottom the first time, all works fine, after that you change tab and when you return the content don't render any more.
Expected behavior:
Every time you select the tab the Stack must be render. In other words, I am able to see the content of the Stack inside the Tab every time I navigate to the Tab.
package
version
#react-navigation/native
6.0.6
#react-navigation/material-bottom-tabs
6.0.9
#react-navigation/native-stack
6.2.5
react-native-safe-area-context
3.3.2
react-native-screens
3.8.0
react-native
0.64.2
expo
43.0.0
Faced the same problem.
Found solution here: https://github.com/software-mansion/react-native-screens/issues/1197#issuecomment-993682256
You should wrap your nested navigator with a View that has collapsable false.
Example with my code:
const MealsNavigator = () => (
<NavigationContainer>
<TabNavigator />
</NavigationContainer>
)
const TabNavigator = () => (
<Tab.Navigator initialRouteName="Meals" {...TabProps} >
<Tab.Screen name="Meals" component={StackNavigator} options={{ headerShown: false, tabBarIcon: ({ color }) => (<Ionicons name='ios-restaurant' size={24} color={color} />), tabBarColor: Colors.primaryColor }} />
<Tab.Screen name="Favorites" component={FavoritesScreen} options={{ tabBarIcon: ({ color }) => (<Ionicons name='ios-star' size={24} color={color} />), tabBarLabel: 'Favorites!', tabBarColor: Colors.accentColor }} />
</Tab.Navigator>
)
const StackNavigator = () => (
<View style={{ flex: 1 }} collapsable={false}>
<Stack.Navigator initialRouteName="Categories" screenOptions={{
headerStyle: { backgroundColor: Platform.OS === "android" ? Colors.primaryColor : '' }, headerTintColor: Platform.OS === "android" ? 'white' : Colors.primaryColor
}} >
<Stack.Screen name="Categories" component={CategoriesScreen} options={{ title: 'Meal Categories' }} />
<Stack.Screen name="CategoryMeals" component={CategoryMealsScreen} options={({ route }) => ({ title: route.params.title })} />
<Stack.Screen name="MealDetail" component={MealDetailScreen} options={({ route }) => ({ title: route.params.title })} />
</Stack.Navigator>
</View>
)

How to send props from createBottomTabNavigation to every tab screen?

I am using createBottomTabNavigation and I have 4 screens which I can access by pressing the tab bar screen in the bottom of my screen. I am also using Stack Navigation to display the title of the screen there and also all screens have the same settings icon.
I could make the same function in every screen that takes care of onPress event on the Settings icon but that is repetitive and I don't want to do it.
My question is - is there a way for me to pass a function as a props from the App component which holds the bottom navigation to every screen?
App screen code:
<NavigationContainer >
<Tab.Navigator initialRouteName="Home" tabBarOptions={{
activeTintColor: '#FF9F0A',
inactiveTintColor:'white',
style: {
backgroundColor:'#000000',//color you want to change
borderTopWidth: 0,
paddingTop:5,
paddingBottom:5,
},
}}>
<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}/>
),
}}/>
Charging screen:
function Charging() {
return (
<View style={globalStyles.container}>
<Text>Charging</Text>
<StatusBar style="auto" />
</View>
);
}
export default function ChargingStackScreen() {
return (
<ChargingStack.Navigator>
<ChargingStack.Screen name="CHARGING" component={Charging} options={{
headerRight: () => (
<View style={globalStyles.headerRight}>
<SettingsIcon />
</View>
),
headerTitleAlign:'left',
headerTintColor: 'white',
headerTitleStyle: globalStyles.headerTitle,
headerStyle: globalStyles.header
}}/>
</ChargingStack.Navigator>
);
}
So what I think you should do is have the header as a separate component, where you can use the useNavigation hook (assuming you're using the latest version of react-navigation), and have the settings button do the navigation you need. Then just render the header component once above the Tab.Navigator instead of rendering it on every screen.
Something like:
function Header(props){
const navigation = useNavigation();
// component code
<SettingsButton onPress={() => navigation.navigate(whatever)}/>
}
And then I am pretty sure (not 100% though) that you can render it in your NavigationContainer, something like:
<NavigationContainer >
<Header/>
<Tab.Navigator initialRouteName="Home" tabBarOptions={{
// rest of the code

Reversing tab navigator direction to support RTL react navigation

I have been trying to change the tab direction to RTL instead of LTR. Unfortunately, I cannot find out how it works. I used flextDirection in tabBarStyle or style props as "row" or "row-reverse", but when I did so, the whole tab was removed. It only appeared when using column or column-reverse showing at the top or bottom of the screen. Here is my code:
const Tab = createMaterialBottomTabNavigator();
<Tab.Navigator
activeColor={theme.colors.text}
inactiveColor={theme.colors.textAlt}
barStyle={{
backgroundColor: theme.colors.background,
flexDirection: "row-reverse", //In this case an empty tab bar only appears with no screens. Screens only appear when it changes to column
}}
shifting={true}
screenOptions={defaultNavOptions}>
<Tab.Screen
name={userConfig.appTexts.homeScreenName}
component={AppNavigator}
options={{
tabBarIcon: ({ color, size }) => {
return <Ionicons name="ios-home" color={color} size={22} />;
},
}}
initialParams={{ theme, taxonomy }}
/>
<Tab.Screen
name={userConfig.appTexts.settingScreenName}
component={SettingNavigator}
options={{
tabBarIcon: ({ color, size }) => {
return <Ionicons name="ios-settings" color={color} size={22} />;
},
}}
initialParams={{ theme }}
/>
<Tab.Screen
name={userConfig.appTexts.savedScreenName}
component={PostNavigator}
options={{
tabBarIcon: ({ color, size }) => {
return <Ionicons name="md-bookmark" color={color} size={22} />;
},
}}
initialParams={{ saved: true, theme }}
/>
</Tab.Navigator>
I guess you can change style in the tabBarOptions :
<Tab.Navigator
tabBarOptions={{
style: {transform: [{scaleX: -1}]},
}}> {Your}
</Tab.Navigator>
Simply reverse your Tab screens order inside Tab Navigator. So move the last screen to be the first and...