How do I hide the shadow under react-navigation headers? - react-native

How do I hide the shadow under react-navigation headers?
They look like this.

Add the following to the navigationOptions header style.
const AppNavigation = StackNavigator(
{
'The First Screen!': { screen: FirstScreen },
},
{
navigationOptions: {
header: {
style: {
elevation: 0, // remove shadow on Android
shadowOpacity: 0, // remove shadow on iOS
},
},
},
},
);
The documentation isn't great yet, but you can learn about navigationOptions in the React Navigation Docs.

in react navigation V5 this how you can do it:
to do it for all screens apply screenOptions prop to <Stack.Navigator>
in example:
<Stack.Navigator
screenOptions={{
headerStyle: {
elevation: 0,
shadowOpacity: 0
},
}}
/>
</Stack.Navigator>
to do it for a specific screen apply options prop to <Stack.Screen>
in example:
<Stack.Screen
name="Example"
component={ExampleComponent}
options={{
headerStyle: {
elevation: 0,
shadowOpacity: 0
},
}}
/>
UPDATE V6:
since released React Navigation V6, you can't hide header shadow using headerStyle option. instead of that you can use bolean option headerShadowVisible and set it to be false like example bellow:
<Stack.Screen
name="Example"
component={ExampleComponent}
options={{headerShadowVisible: false}}
/>

The following works for me as the original Stylesheet uses "borderBottomWidth" on iOS:
const navigator = StackNavigator(screens, {
navigationOptions: {
headerStyle: {
elevation: 0,
shadowOpacity: 0,
borderBottomWidth: 0,
}
}
});

I don't know how much this answer will value, but sharing my code to let you know that this worked for me for react-navigation version: 3.9.1
const AppNavigation = StackNavigator(
{
FirstScreen,
},
{
defaultNavigationOptions: {
headerStyle: {
elevation: 0, //for android
shadowOpacity: 0, //for ios
borderBottomWidth: 0, //for ios
},
},
})

In v5 you can do the following
<Stack.Navigator>
<Stack.Screen
name="Example"
component={ExampleComponent}
options={{
headerStyle: {
elevation: 0,
shadowOpacity: 0
},
}}
/>
</Stack.Navigator>

Good afternoon, React Navigation 6:
<Stack.Navigator screenOptions={{headerShadowVisible:false}}>

This works for me:
export const AppNavigator = StackNavigator(
{
Login: { screen: LoginScreen },
Main: { screen: MainScreen },
Profile: { screen: ProfileScreen },
},
navigationOptions: {
headerStyle: {
elevation: 0,
shadowOpacity: 0,
}
}
);
or
export const AppNavigator = StackNavigator(
{
Login: { screen: LoginScreen },
Main: { screen: MainScreen },
Profile: { screen: ProfileScreen },
},
header: {
style: {
elevation: 0, //remove shadow on Android
shadowOpacity: 0, //remove shadow on iOS
}
}
);

in react-navigation version 5.x.x:
<Tab.Navigator
tabBarOptions={{
activeTintColor: colors.darkGray,
labelStyle: { fontSize: 12 },
style: { backgroundColor: colors.white, borderTopWidth: 0, elevation: 0, shadowOpacity: 0, },
}}
>

Try passing cardStyle: { shadowColor: 'transparent' }
export const AppNavigator = StackNavigator(
{
Login: { screen: LoginScreen },
Main: { screen: MainScreen },
Profile: { screen: ProfileScreen },
},
cardStyle: { shadowColor: 'transparent' }
As per this question React Navigation Stack Navigator default shadow styling

I have been trying to solve this problem for the past couple of hours and have finally found the solution.
The problem in my case was that the header was in a different Z position than the rest of the other components.
try:
const styles = {
headerStyle: {
zIndex: 1
}
}

As of 2019 this answer doesn't work in version 3.
The new way of doing it is:
const AppNavigation = StackNavigator(
{
'The First Screen!': { screen: FirstScreen },
},
{
defaultNavigationOptions: {
headerStyle: {
elevation: 0,
shadowOpacity: 0,
},
},
},
);

I'm using react navigation v5, i use this code :
const HomeStackScreen = ({navigation}) => (
<HomeStack.Navigator
initialRouteName="Home"
headerMode="screen"
mode="modal"
screenOptions={{
headerStyle: {
backgroundColor: COLORS.WHITE,
elevation: 0, // remove shadow on Android
shadowOpacity: 0, // remove shadow on iOS
borderBottomWidth: 0,
},
headerTintColor: COLORS.GREY,
headerTitleStyle: {
fontFamily: 'Montserrat-SemiBold',
fontWeight: '600',
fontSize: 18,
},
}}>
<HomeStack.Screen
name="Home"
component={Home}
options={{
title: 'Expanded',
headerLeft: () => <RenderHeaderLeft />,
headerRight: () => <RenderHeaderRight navigation={navigation} />,
headerTitleAlign: 'left',
}}
/>
<HomeStack.Screen name="HomeDetails" component={HomeDetails} />
</HomeStack.Navigator>
);
put shadowOpacity and elevation inside headerStyle

it is:
options: {{
headerShadowVisible: false,
}}
check the docks for more info:
https://reactnavigation.org/docs/native-stack-navigator

You can try this, and it worked for me !
export const SignedOut = StackNavigator({
SignIn: {
screen: SignInScreen,
navigationOptions: {
title: "SignIn",
headerStyle: {
shadowOpacity: 0, // This is for ios
elevation: 0 // This is for android
}
}
}
});

The shadow is achieved via elevation, use:
headerStyle: {
backgroundColor: 'white',
shadowColor: 'transparent',
elevation: 0,
},

For React Native Navigation 5
<Stack.Screen
name={"Profile"}
component={Profile}
options={{
headerTitle: "Profile",
headerHideShadow: true,
}}
/>
Or
<Stack.Navigator
screenOptions={{
headerHideShadow: true,
}}
>

Related

react-native-navigation createMaterialBottomTabNavigator hide tab from tabBar

I need your help :) I use createMaterialBottomTabNavigator and need to hide specific screen tab from bar :)
her is my navigation config`
export const tabNavigation = [
{
name: 'Home',
component: HomeNavigation,
},
{
name: 'History',
component: HistoryNavigation,
},
{
name: 'QrScanner',
component: QrScannerNavigation,
},
{
name: 'Payments',
component: PaymentsNavigation,
},
{
name: 'CardInfo',
component: CardInfo,
},
];
here is navigation`
<Tabs.Navigator
initialRouteName="Home"
barStyle={{
backgroundColor: RGB(colors.white, 0.0),
borderColor: 'transparent',
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 0,
shadowRadius: 0,
elevation: 0,
display: mainMenuState ? 'none' : 'flex',
}}
>
{tabNavigation.map((nav, index) => {
const { name, component } = nav;
return (
<Tabs.Screen
key={index}
name={name}
component={component}
options={{
tabBarVisible: false,
title: '',
tabBarIcon: (tabState) => {
return (
<SvgIcon
fileName={tabState.focused ? name.toLowerCase() + '-active' : name}
width={26}
height={26}
icon={true}
/>
);
},
}}
/>
);
})}
</Tabs.Navigator>
so how can i hide card info tab from tab bar?
please help !!!!

How can I conditionally set tabs in createBottomTabNavigator?

I have a static data file (json) that stores information like facebook page link. If the facebook page link is empty, I do NOT want the Follow Us tab to show. The facebook page link is stored in businessDataJSON.facebook. Is there a way to only show the Follow Us Tab if businessDataJSON.facebook is not empty (empty string)? This is my App.js:
const ListStack = createStackNavigator(
{
ListCategories: ListCategoriesScreen,
ListCategoryItems: ListCategoryItemsScreen
},
{
initialRouteName: "ListCategories",
defaultNavigationOptions: {
headerStyle: {
backgroundColor: businessDataJSON.theme.navigationBarBackground
},
headerTintColor: businessDataJSON.theme.navigationBarTint,
headerTitleStyle: {
fontWeight: "bold"
}
}
}
);
const FollowUsStack = createStackNavigator(
{
FollowUs: FollowUsScreen
},
{
initialRouteName: "FollowUs",
defaultNavigationOptions: {
headerStyle: {
backgroundColor: businessDataJSON.theme.navigationBarBackground
},
headerTintColor: businessDataJSON.theme.navigationBarTint,
headerTitleStyle: {
fontWeight: "bold"
}
}
}
);
export default createAppContainer(
createBottomTabNavigator(
{
ListTab: {
screen: ListStack,
navigationOptions: {
title: businessDataJSON.theme.tabBarListTitle,
tabBarIcon: ({ tintColor }) => (
<Icon
name={businessDataJSON.theme.tabBarListIcon}
size={17}
color={tintColor}
/>
)
}
},
FollowUsStack: {
screen: FollowUsStack,
navigationOptions: {
title: "Follow Us",
tabBarIcon: ({ tintColor }) => (
<Icon name="users" size={17} color={tintColor} />
)
}
}
},
{
tabBarOptions: {
activeTintColor: businessDataJSON.theme.tabBarIconActive,
inactiveTintColor: businessDataJSON.theme.tabBarIconInactive,
style: {
elevation: 8,
...Platform.select({
ios: { paddingTop: 4, paddingBottom: 4 },
android: {
borderTopWidth: 0,
paddingTop: 6,
paddingBottom: 6
}
})
}
}
}
)
);
Yes but you would need to make the creation of the tabs dinamic wich leads to the navigation prop to be lost and make a nightmare to use it without redux. The simple approach that i can see is to use a root createSwitchNavigator with a loading screen/start screen and the tabs as the 2nd screen. in the loading screen you check if there is your facebook page, and navigate to them accordingly. this example is for auth, but it works in your case . trust me, the navigation props is a nightmare to manage.

How to Style React-Navigation tab navigator with a mobx variable

I think I've just been staring at this too long, and now my brain doesn't work. I have mobx stores, one of which houses a basic theme color value. I want to pass this into my react-navigation tab background color, but I can't figure out how to do it. We are using Typescript, and that might be part of what is confusing me, because every time I try to inject my store, I get a bunch of errors.
Anyway, if someone could help me figure out how to either inject my store properly, or to pass a prop to my createMaterialTopTabNavigator function, I would greatly appreciate it.
Here is my top tab navigator code:
export const SignedInWithGroup = createMaterialTopTabNavigator(
{
Home: {
screen: MeetingStack,
navigationOptions: {
tabBarLabel: 'Advocacy Day',
tabBarIcon: <Ionicons name="md-home" size={24} />,
},
},
Legislators: {
screen: Legislators,
navigationOptions: {
tabBarLabel: 'Legislators',
tabBarIcon: <Ionicons name="ios-people" size={24} />,
},
},
Messages: {
screen: Messages,
navigationOptions: {
tabBarLabel: 'Messages',
tabBarIcon: <Ionicons name="ios-chatboxes" size={24} />,
},
},
Directory: {
screen: DirectoryStack,
navigationOptions: {
tabBarLabel: 'Directory',
tabBarIcon: <MaterialIcons name="contacts" size={24} />,
},
},
More: {
screen: MoreStack,
navigationOptions: {
tabBarLabel: 'More',
tabBarIcon: <MaterialIcons name="more" size={24} />,
},
},
},
{
tabBarPosition: 'bottom',
tabBarOptions: {
showIcon: true,
style: {
paddingTop: Platform.OS === 'android' ? 0 : 0,
backgroundColor: "#CCBE00", //Replace with theme color
},
tabStyle: {
padding: 0,
},
labelStyle: {
marginTop: Platform.OS === 'ios' ? 8 : 0,
marginBottom: Platform.OS === 'ios' ? 20 : 10,
marginLeft: 15,
fontSize: 7,
color: 'white',
},
},
}
);
export const createRootNavigator = (props:any, signedIn = false) => {
console.log("Props");
console.log(props);
return createSwitchNavigator(
{ SignedInWithGroup: { screen: SignedInWithGroup }, SignedOut },
{ initialRouteName: signedIn ? 'SignedInWithGroup' : 'SignedOut' }
);
};
and here is what is in my app.js:
const Layout = createRootNavigator(signedIn);
return (
<Provider {...stores}>
<Layout />
</Provider>
);
Solution
Use your custom tabbar from MaterialTopTabBar.
Install the react-navigation-tabs module. Because, react-navigation's TabNaviagtion is from react-navigation-tabs. (srcs)
$ yarn install react-navigation-tabs
or
$ npm install react-navigation-tabs --save
Make your custom tabbar component observing store(MobX) for the tabBarComponent option . I do not write code related in MobX or Redux.
import React, { Component } from 'react';
import { MaterialTopTabBar } from 'react-navigation-tabs';
// create a component
class TabBar extends Component {
  render() {
    return (
      <MaterialTopTabBar
        {...this.props}
        style={{ backgroundColor: 'green' }} // Replace with theme color. You should use observing variable from MobX or Redux.
      />
    );
  }
}
//make this component available to the app
export default TabBar;
Apply your custom tabbar in createMaterialTopTabNavigator.
const TabNavigation = createMaterialTopTabNavigator(
  {
    Home: HomeScreen,
    Login: HomeScreen,
    Register: HomeScreen,
  },
  {
    tabBarComponent: (props) => { // Use your custom tabbar here.
return (
<TabBar
{...props}
/>
);
},
tabBarPosition: 'bottom',
tabBarOptions: {
showIcon: true,
style: {
paddingTop: Platform.OS === 'android' ? 0 : 0,
},
tabStyle: {
padding: 0,
},
labelStyle: {
marginTop: Platform.OS === 'ios' ? 8 : 0,
marginBottom: Platform.OS === 'ios' ? 20 : 10,
marginLeft: 15,
fontSize: 7,
color: 'white',
},
},
}
);
Why?
As I wrote, react-navigation-tabs is used as TabNavigation basically in react-navigation And you can use custom view through tabBarComponent option when you createTabNavigator
There are some mudules you can use.
Navigators
createBottomTabNavigator
createMaterialTopTabNavigator
Views
BottomTabBar
MaterialTopTabBar (You used this view)
Utils
createTabNavigator
Thus, extending component or making your custom tabbar from BottomTabBar or MaterialTopTabBar can be one of the easily solutions.

Transparent background for header using createStackNavigator, React Native

I created a project using CRNA that uses React-Navigation. In one of the screen I have a background image that cover the entire screen and I want to including the header.
Like this image :
Should I just hide the header and use a View that contains the element that I want? If yes will this cause any trouble in case of deep linking?
Solution
React Navigation offers a cool props called headerTransparent that can be used in
order to render something under the header.
So the code at the should look like this :
static navigationOptions = {
headerTransparent: true
}
Right now with React Navigation 5 we can do something like this:
{
headerShown: true,
headerTransparent: true,
}
For example:
const Screen = ({ navigation }) => {
navigation.setOptions({
headerShown: true,
headerTransparent: true,
});
return (
<View>
<Text>Render your component</Text>
</View>
);
};
this worked for me :
navigationOptions: {
...
headerTransparent: true,
headerStyle: {
backgroundColor: 'transparent',
...
}
}
To achieve this effect you need to follow those steps:
Change the style of the navigation header with absolute position, transparent background and no border.
Use ImageBackground component as parent component for your screen with the image that you want to use as background.
Add padding top to this ImageBackground to fix the overlapping.
So your code should looks something similar to this:
import React, {Component} from 'react';
import {
StyleSheet,
Button,
ImageBackground,
Platform,
} from 'react-native';
import {
createStackNavigator,
} from 'react-navigation';
class HomeScreen extends Component {
render() {
return (
<ImageBackground
style={styles.container}
source={require('./images/bg.png')}
>
<Button
onPress={() => {}}
title="Just a button"
/>
</ImageBackground>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Platform.OS === 'ios' ? 60 : 80,
}
});
const App = createStackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: {
title: 'Home',
headerStyle: {
position: 'absolute',
backgroundColor: 'transparent',
zIndex: 100,
top: 0,
left: 0,
right: 0,
elevation: 0,
shadowOpacity: 0,
borderBottomWidth: 0,
}
},
}
})
export default App;
Solution:
navigationOptions: {
headerTransparent: {
position: 'absolute',
backgroundColor: 'transparent',
zIndex: 100,
top: 0,
left: 0,
right: 0
}
If using React Navigation 6.x, the option is the same headerTransparent:
<Stack.Screen
name="BottomTab"
component={BottomTabNavigator}
options={{
headerTransparent: true,
}}
/>
You need to use headerTransparent and headerShadowVisible otherwise if you just use headerTransparent a shadow will be left. This works with React Navigation 6.x. See de docs here https://reactnavigation.org/docs/native-stack-navigator/#headershadowvisible
<Stack.Screen name='Main' component={Main}
options={{
title: 'MainPage',
headerTransparent: true,
headerShadowVisible: false
}}
/>
I have achieved it setting the navigation options like this:
BirdDetails.navigationOptions = () => {
return {
...NavStyle,
headerStyle: {
backgroundColor: 'transparent',
},
headerTransparent: {
position: 'absolute',
},
headerLeft: <Back></Back>,
headerRight: <HeaderDetailsRight></HeaderDetailsRight>,
};
};
With V5
<NavigationContainer>
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: true,
headerTransparent:true
}}
>
<Stack.Screen name="Home" component={HomeScreen}/>
<Stack.Screen name="Detail" component={DetailScreen}/>
<Stack.Screen name="Setting" component={SettingScreen}/>
</Stack.Navigator>
</NavigationContainer>
this worked for me:
headerStyle: {elevation:0, backgroundColor:"transparent"}
set elevation to 0 so there is no shadow.
I did it this way, it has one flaw though, in the the background color must be hard-coded. This approach is specifically for ScrollView and starts out transparent becoming opaque (keeping the original text).
Since this was designed for native stack navigator to leverage iOS' large text the headerHeight also needs to be adjusted to the proper values.
const navigation = useNavigation();
return (
<ScrollView
onLayout={(e) => {
navigation.setOptions({
headerStyle: {
backgroundColor: "transparent",
},
});
}}
onScroll={(e) => {
const headerOpacity =
Math.min(
Math.max(e.nativeEvent.contentOffset.y, 0) / headerHeight,
1.0
) ?? 0.0;
navigation.setOptions({
headerStyle: {
elevation: headerOpacity,
backgroundColor: `rgba(255,0,0,${headerOpacity})`,
},
});
}}
scrollEventThrottle={16}
contentInsetAdjustmentBehavior="never"
>

How to navigate to a new page using navigation.navigate without the tab bar in react native

I have a tab Navigation and Navigation bar in one of the tab. I would like to navigate to the next screen. I tried out the tutorial in the https://snack.expo.io/#react-navigation/stacks-in-tabs and added this line in the code:
static navigationOptions = ({navigate, navigation}) => ({
title: "NOTIFICATION HISTORY",
headerTitleStyle: {
fontWeight: "bold",
color: Colors.tintColor,
alignSelf: "center"
},
headerStyle: {
backgroundColor: "white",
shadowOpacity: 0,
shadowOffset: {
height: 0
},
shadowRadius: 0,
borderBottomWidth: 0,
elevation: 0
}
});
export const NotiStackNavigator = StackNavigator(
{
Noti: {
screen: NotiScreen
},
NotiHistory: {
screen: NotiHistScreen
}
},
{
navigationOptions: () => ({
// gesturesEnabled: false,
headerTitleStyle: {
fontWeight: "bold",
color: Colors.tintColor,
alignSelf: "left"
},
headerStyle: {
backgroundColor: "white",
shadowOpacity: 0,
shadowOffset: {
height: 0
},
shadowRadius: 0,
borderBottomWidth: 0,
elevation: 0
}
})
}
export const MainTabNavigator = TabNavigator(
{
Home: {
screen: HomeStackNavigator
},
Noti: {
screen: NotiStackNavigator
},
Settings: {
screen: SettingsScreen
}
},
{
navigationOptions: ({ navigation }) => ({
// Set the tab bar icon
tabBarIcon: ({ focused }) => {
const { routeName } = navigation.state;
let iconName;
switch (routeName) {
case "Home":
iconName = "home";
break;
case "Noti":
iconName = "bell-o";
break;
case "Settings":
iconName = "cog";
}
return (
<FontAwesome
name={iconName}
size={24}
color={focused ? Colors.tabIconSelected : Colors.tabIconDefault}
/>
);
}
}),
// Put tab bar on bottom of screen on both platforms
tabBarComponent: TabBarBottom,
tabBarPosition: "bottom",
// Disable animation so that iOS/Android have same behaviors
animationEnabled: false,
swipeEnabled: false,
// Show the labels
tabBarOptions: {
showLabel: true,
activeTintColor: Colors.tabIconSelected,
inactiveTintColor: Colors.tabIconDefault,
style: {
backgroundColor: Colors.tabBar
}
}
}
);
I can have the tab and navigation going. When the navigation went to the next screen, the tabs still there and the name of the tab change to the new
screen's name. How do I get rid of the tab when going to the next screen?
In your details screen for your StackNavigator replace with this line :
Details: { screen: DetailsScreen, navigationOptions: { tabBarVisible: false } },
or set it as a prop for the specific screen in navigationOptions