React Native Bottom Tab Navigation content styling - react-native

I am coding an app with a bottom Tab Navigator nested within a Stack Navigator, I am trying to target the content styling for all the screen within this Tab.Navigator but the commands I am using are not working
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function TabNavigator(){
return (
<Tab.Navigator
// tabBarOptions={{
// style: {backgroundColor: "#511cff"} // deprecated metro says to place it into screenOptions under tabBarStyle
// }}
screenOptions={{
// headerStyle: { backgroundColor: "#2f28fc" },
tabBarActiveTintColor: "#F8F2DA",
tabBarOptions:{
contentStyle: {backgroundColor:"#511cff"},
sceneContainerStyle: {backgroundColor:"#511cff"},
},
tabBarStyle: {
backgroundColor: "#2f28fc",
contentStyle: {backgroundColor:"#511cff"},
sceneContainerStyle: {backgroundColor:"#511cff"},
},
contentStyle: {backgroundColor:"#511cff"},
sceneContainerStyle: {backgroundColor:"#511cff"},
headerShown: false,
}}
>
</Tab.Navigator>
)
}
export default function App() {
return (
<>
<StatusBar style="light" />
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerStyle: { backgroundColor: "#2f28fc" },
headerTintColor: "#F8F2DA",
sceneContainerStyle: { backgroundColor: "#511cff" }
}}
>
<Stack.Screen
name='ExpensesView'
component={TabNavigator}
screenOptions={{
sceneContainerStyle:{ backgroundColor: "#511cff" },
contentStyle: {backgroundColor:"#511cff"}
}}
/>
</Stack.Navigator>
</NavigationContainer>
</>
);
}
From looking through here: https://github.com/react-navigation/react-navigation/issues/8076
I think the solution would be to use the sceneContainerStyle property within Navigator like so:
<Tab.Navigator
sceneContainerStyle= {{
backgroundColor: "#511cff"
}}

I was able to solve this by using sceneContainerStyle property outside of the screenOptions property. Why they have moved it out of the screenOptions for just TabNavigator is a mystery, but it works.
CODE:
<Tab.Navigator
tabBar={props => <CustomTabBar {...props} />}
screenOptions={({ route }) => ({
headerShown: false,
})}
sceneContainerStyle={styles.sceneStyle}>

I read the documentation for you and found that you syntax is not valid.
Their is nothing like tabBarOptions in it.
here's the link of how we can use the options in tab Bar
https://reactnavigation.org/docs/screen-options
Hope this will help u.

Related

How to avoid the suddenly chop down on react native navigator

Here is the code I got:
I got a Stack Navigator that store two screens:
<Stack.Navigator
initialRouteName="FirstScreen"
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="FirstScreen" component={FirstScreen}/>
<Stack.Screen name="DrawerNavigator" component={DrawerNavigator}/>
</Stack.Navigator>
And I got a DrawerNavigator which have my MainNavigator, which is the screen cap I provided:
<Drawer.Navigator
initialRouteName="MainNav"
screenOptions={{
drawerStyle: {
backgroundColor: getPrimaryColor()
},
drawerLabelStyle: {
color: 'white'
}
}}>
<Drawer.Screen
name="MainNav"
component={MainNav}
options={({route}) => (getShowOptions(route))}/>
</Drawer.Navigator>
Inside the MainNav, it have two page, one is home, another is detail:
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
options={{ headerShown:false }}
name="Home"
component={Home}
/>
<Stack.Screen
name="Detail"
component={Detail} />
</Stack.Navigator>
As you may noticed that it has a getShowOptions method, which is control the actual nav bar display:
function getShowOptions(route) {
const routeName = getFocusedRouteNameFromRoute(route);
const icon =
let options = {
headerStyle: {
backgroundColor: getPrimaryColor()
},
headerTintColor: '#fff',
headerTitleAlign: 'center',
title: i18n.t('Home'),
drawerIcon: ({focused, size}) => (
<View
style={[{
height: iconSize,
width: iconSize
}
]}>
{icon}
</View>
)
};
if (routeName === 'Detail') {
options.headerShown = false;
}
return options;
}
When the screen is push to "Detail", it will hide the header, to show a header that have a back button, but when it put back to "Home", it should use back the "Drawer" menu button. As u can see the issue happen when we switch back and forward between the drawer navigation bar and the stack navigation bar.
The use case is pretty simple, we would like to have the "menu" when the "home" screen is appear, and "back" appear when the "detail" screen is presented. It seems that the React Native Stack Navigator and Drawer Navigator can't work together very well. Any suggestions?

How to disable black shadow in react native navigation?

I try to set the background of a card to transparent, but somehow a black shadow remains. How do I remove the the shadow?
const screenOptions = useMemo<StackNavigationOptions>(
() => ({
...TransitionPresets.SlideFromRightIOS,
safeAreaInsets: { top: 0 },
// presentation: "modal",
cardStyle: {
backgroundColor: "transparent",
},
cardShadowEnabled: false,
}),
[]
);
const screenAOptions = useMemo(() => ({ headerShown: false }), []);
return (
<NavigationContainer independent={true}>
<Stack.Navigator
screenOptions={{ headerShown: false }}
headerMode="screen"
>
<Stack.Screen
name="Home"
options={screenOptions}
component={() => <View style={{ flex: 1 }} />}
/>
</Stack.Navigator>
</NavigationContainer>
As a site note: The Navigator is located in a bottom drawer. However, the shadow appears only with the Navigator and not with other components located directly in the bottom drawer. Thats why i think its related to the navigator.

'focus' listener not calling every time. React Native

I am new in react native technology. I have used following hierarchy in my react native app.
I have used Stack.Navigator in which I am using various screen, I. Login, II. Sign-Up, III. TabBar Screen.
In TabBar screen I have used various individual Stack.Navigator because I have to show tab bar on every child screen.
Now problem is that I have to update some value on tab screen when user click on that particular screen. It is calling once at first time, not working second time.
I have used following code for execute 'focus' listener on tab screen :-
onScreenFocus = () => {
this.reloadFavrouite()
alert("again calling")
}
componentDidMount() {
this.props.navigation.addListener('focus', () => this.onScreenFocus())
this.reloadFavrouite()
}
'focus' listener work well If I am not use individual Stack.Navigator at every tab screen, but it is creating another issue is that tab bar not showing in child screen.
I have used this tab navigator code:- Please check
export default class TabNavigator extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Tab.Navigator initialRouteName='Home' lazy={true} tabBarOptions={
{
style: {
backgroundColor: '#FFFFFF',
borderTopLeftRadius: 25,
borderTopRightRadius: 25,
overflow: 'hidden',
borderColor: 'transparent',
}
}
}>
<Tab.Screen name="HomeNavigator" component={HomeNavigator}
options={{
tabBarLabel: ({ focused }) => {
const tintColortab = focused ? "#006C35"
: "#000000"
return (
<Text style={{ color: tintColortab, fontSize: 8, fontFamily: "Roboto-Bold", marginBottom: 6 }}>{StringsOfLanguages.Home}</Text>
)
},
tabBarIcon: ({ focused }) => {
const tintColortab = focused ? "#006C35"
: "#000000"
return (
<Image source={require('../../../assets/images/TabBarIcons/ic_home_selected/ic_home_selected.png')}
style={{ marginTop: 10, tintColor: tintColortab }}>
</Image>
)
}
}}>
</Tab.Screen>
<Tab.Screen name="FavouriteNavigator" component={FavouriteNavigator}
options={{
tabBarLabel: ({ focused }) => {
const tintColortab = focused ? "#006C35"
: "#000000"
return (
<Text style={{ color: tintColortab, fontSize: 8, fontFamily: "Roboto-Bold", marginBottom: 6 }}>{StringsOfLanguages.Favorite}</Text>
)
},
tabBarIcon: ({ focused }) => {
const tintColortab = focused ? "#006C35"
: "#000000"
return (
<Image source={require('../../../assets/images/TabBarIcons/ic_favorits_unselected/ic_favorite_unselected.png')}
style={{ marginTop: 10, tintColor: tintColortab }}>
</Image>
)
}
}}
>
</Tab.Screen>
</Tab.Navigator>
);
}
And individual navigation is like :-
class HomeNavigator extends React.Component {
render() {
return (
<NavigationContainer independent={true}>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} options={{ headerShown: false }} />
<Stack.Screen name="AllRestuarent" component={AllRestuarent} options={{ headerShown: false }} />
<Stack.Screen name="AllLaundry" component={AllLaundry} options={{ headerShown: false }} />
<Stack.Screen name="AllEntertainment" component={AllEntertainment} options={{ headerShown: false }} />
<Stack.Screen name="Offer" component={Offer} options={{ headerShown: false }} />
<Stack.Screen name="ComponyMap" component={ComponyMap} options={{ headerShown: false }} />
</Stack.Navigator>
</NavigationContainer>
);
}
}
class FavouriteNavigator extends React.Component {
render() {
return (
<NavigationContainer independent={true}>
<Stack.Navigator>
<Stack.Screen name="Favorites" component={Favorites} options={{ headerShown: false }} />
<Stack.Screen name="Offer" component={Offer} options={{ headerShown: false }} />
<Stack.Screen name="ComponyMap" component={ComponyMap} options={{ headerShown: false }} />
</Stack.Navigator>
</NavigationContainer>
);
}
}
You are not using focus listener in the right way according to your current version, You are using react-navigation v5 and you are adding a listener the way it is used in react-navigation v4, Here is a solution to your problem.
class YourClassComopnent extends React.Component {
componentDidMount() {
/*
Now you can access to isFocused prop and
this prop will be true whenever your screen is
in the focus.
*/
if(this.props.isFocused) this.onScreenFocus()
this.reloadFavrouite()
}
render() {
// Get it from props
const { isFocused } = this.props;
}
}
// Wrap and export
export default function(props) {
const isFocused = useIsFocused();
// pass your class here
return <YourClassComopnent {...props} isFocused={isFocused} />;
}
Link to docs, how you can use isFocused in react-navigation v5

how to get drawerOpen() to stack navigator screen Options

i have this stack navigator:
const StackNavigator = () => (
<Stack.Navigator headerMode="screen" navigationOptions screenOptions={ss}>
<Stack.Screen name="Main" component={MainScreen} headerMode="screen" />...............
and i have object of screen options:
const ss = {
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
gestureEnabled: true,
gestureDirection: "horizontal",
headerTitleAlign: "center",
headerHideShadow: true,
headerTintColor: "red",
headerStyle: {
borderBottomWidth: 0.5,
borderColor: "white",
backgroundColor: "#1d2731",
},
headerTitleStyle: {
color: "white",
},
headerLeft: () => <AnimateHamburger navigation={navigation} />,
};
no when i get inside the component AnimatedHamburger
i dont get the props of openDrawer ...i get "...
navigation.openDrawer is not function....................
the AnimateHamburger component:
const AnimateHamburger = ({ navigation }) => {
console.log(navigation);
const isDrawerOpen = useIsDrawerOpen();
const toggleMenu = () => {
navigation.openDrawer();
};
return (
<View style={styles.icon}>
<Icon
style={styles.icon}
onPress={toggleMenu}
name={isDrawerOpen ? "enter" : "bars"}
type={isDrawerOpen ? "antdesign" : "font-awesome"}
color="black"
size={30}
/>
</View>
);
};
PLEASE help me how can i get the navigation props to toggle my drawer from the AnimateHamburger component
If you receiving openDrawer is not a function that's probably you are trying to access this method in a nested navigator which don't know about the parent drawer navigator. You can access drawer methods with DrawerAction from react-navigation take a look here:
https://reactnavigation.org/docs/drawer-actions
And use it like this:
https://reactnavigation.org/docs/nesting-navigators/#navigator-specific-methods-are-available-in-the-navigators-nested-inside

React-navigation - goBack behaviour in nested navigators (stack inside drawer)

I'm using a stack navigator inside drawer navigator - recently upgraded from v4. Trying to implement custom back button on headerLeft. goBack function on the stack screen is going back on the drawer navigator instead of the stack. I don't know if I'm missing something or if it's a bug on v5. The goBack should go to the previous screen in the stack not the drawer. See the gif below; using the gesture goes back on the stack and the default back button on the header goes back onto the stack too. It's only my custom back button with the problem.
export function BlogsStack({navigation}) {
return (
<Stack.Navigator
initialRouteName={'Blogs'}
screenOptions={{
gestureEnabled: true,
gestureDirection: 'horizontal',
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
headerStyle: {
borderBottomWidth: 0,
elevation: 0,
shadowOpacity: 0,
},
headerTintColor: themeVars.headerTintColor,
headerBackground: () => {
return <HeaderBackground />;
},
}}>
<Stack.Screen
name="Blogs"
component={Blogs}
options={{
title: 'Blogs',
headerTitle: () => (
<View>
<HeaderButton title={'Blogs'} />
</View>
),
headerLeft: () => (
<TouchableOpacity
onPress={() => navigation.toggleDrawer()}
style={drawerStyles.menuIconContainer}>
<FeatherIcon
style={drawerStyles.menuIcon}
name="menu"
size={themeVars.hamburgerIconSize}
color={themeVars.hamburgerIconColor}
/>
</TouchableOpacity>
),
headerRight: () => <View />,
}}
/>
<Stack.Screen
name="BlogSingle"
component={BlogSingle}
options={{
headerTitle: () => (
<View>
<HeaderButton title={'Blog'} />
</View>
),
headerLeft: () => (
<TouchableOpacity
onPress={() => navigation.goBack()}
style={drawerStyles.menuIconContainer}>
<FeatherIcon
style={drawerStyles.menuIcon}
name="chevron-left"
size={themeVars.hamburgerIconSize}
color={themeVars.hamburgerIconColor}
/>
</TouchableOpacity>
),
headerRight: () => <View />,
}}
/>
</Stack.Navigator>
);
}
export class Navigation extends Component {
constructor(props, context) {
super(props, context);
}
render() {
return (
<NavigationContainer ref={navigationRef}>
<AppDrawer.Navigator
initialRouteName={'Home'}
drawerContent={props => <DrawerContent {...props} />}
drawerContentOptions={{
labelStyle: {
fontFamily: themeVars.boldFont,
color: themeVars.primaryColor,
},
activeTintColor: 'black',
activeBackgroundColor: 'black',
inactiveTintColor: 'white',
inactiveBackgroundColor: 'white',
itemStyle: {
marginVertical: 0,
borderWidth: 1,
borderColor: 'red',
margin: 0,
padding: 0,
},
}}>
<AppDrawer.Screen
name="Home"
component={HomeStack}
initialRouteName={'Home'}
options={{
drawerLabel: 'Home ',
drawerIcon: () => (
<FeatherIcon
color={themeVars.primaryColor}
name="home"
size={themeVars.drawerIconSize}
/>
),
}}
/>
<AppDrawer.Screen
initialRouteName="Blogs"
backBehavior="order"
name="Blogs"
component={BlogsStack}
options={{
drawerLabel: 'Blogs ',
drawerIcon: () => (
<FontAwesome5
color={themeVars.primaryColor}
name="wordpress"
size={themeVars.drawerIconSize}
/>
),
}}
/>
</AppDrawer.Navigator>
</NavigationContainer>
);
}
}
I sorted out my issue by following the docs. The issue was that I was passing the wrong navigation.
You need to use the correct navigation prop in your header, i.e. by
defining a callback for the options:
https://reactnavigation.org/docs/screen-options#options-prop-on-screen
You're using navigation prop passed from the parent navigator which is
a drawer, so the action is performed in the drawer.
Follow the git issue: https://github.com/react-navigation/react-navigation/issues/8806
To be more clear : we have to get the navigation prop from specific screen itself hence the screen stack will be notified of the history. using hook doesn't do this.