Transparent background for header using createStackNavigator, React Native - 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"
>

Related

React Navigation: Transparent header has no height

If I set headerTransparent: true the other content which was usually rendered below it moves underneath it. How can I avoid that?
My code:
export class RegisterScreen extends Component {
static navigationOptions = {
title: strings.header,
headerTitleStyle: { color: '#fff' },
headerTintColor: '#fff',
headerTransparent: true,
};
render() {
return <Display onSignUpPressed={() => {}} onHelpPressed={() => {}} />;
}
}
With transparent header (it overlaps :( ):
Without transparent header:
I'd like to have the content aligned as if the header had a height. So I want the content to be like in the second picture, but with a transparent header like in the first.
You can now use the headerStyle property to give your header a transparent background, while keeping its height:
static navigationOptions = {
title: strings.header,
headerTitleStyle: { color: '#fff' },
headerTintColor: '#fff',
headerStyle: { backgroundColor: 'transparent' },
};
Header overlaps with the content underneath if headerTransparent: true is set. You need to manually add a top margin or padding according to your situation to your content if you dont want it overlapped. React Navigation won't do it automatically but it provides a hook that gets header height
import { useHeaderHeight } from '#react-navigation/stack';
Now, you can get the height in your component like this:
const headerHeight = useHeaderHeight();
You will need to give you screen component a top padding equivalent to the height of the header ,
On React Native v6.x
Instead of doing
screenOptions={{headerTransparent: true}}
You can apply it in the backgroundColor in the header style like so
screenOptions={{
headerStyle: {
backgroundColor: 'transparent';
}
}}
This is if you wanna keep the padding
Add headerBackground to navigationOptions like this
static navigationOptions = {
title: strings.header,
headerTitleStyle: { color: '#fff' },
headerTintColor: '#fff',
headerTransparent: true,
headerBackground: Platform.select({
ios: <BlurView style={{ flex: 1 }} intensity={98} />,
android: (
<View style={{ flex: 1, backgroundColor: 'rgba(255,255,255,0.7)' }} />
),
}),
};
We can make transparent header with the help of
headerTransparent: true
but with this we also need to give headerStyle like this to make transparent header.
static navigationOptions = {
headerTransparent: true,
headerStyle: { borderBottomWidth: 0 }
};
In my case I make it possible by giving this style to my header.
style:{ position: 'absolute', backgroundColor: 'transparent', zIndex:
100, top: 0, left: 0, right: 0}

How do you make the react-native react-navigation tab bar transparent

Is there a way to make the tab bar transparent? I tried the following but it just showed a white background. Do I need to implement my own tabBarComponent? If so, is there any documentation on that class and what interface I need to implement?
const MainTabNavigator = TabNavigator(
{
MessageCenter: { screen: MessageCenterStack },
Camera: { screen: CameraStack },
},
{
tabBarPosition: 'bottom',
swipeEnabled: true,
animationEnabled: true,
tabBarOptions: {
style: {
backgroundColor: 'transparent',
},
}
}
);
I have to set position absolute and give it a left right and bottom for it the backgroundColor transparent to take effect.
tabBarOptions: {
showIcon: true,
showLabel: false,
lazyLoad: true,
style: {
backgroundColor: 'transparent',
borderTopWidth: 0,
position: 'absolute',
left: 50,
right: 50,
bottom: 20,
height: 100
}
}
I finally got it working on android and ios by adding a container view for the custom tab bar component and make the container absolute positioned and leave the tab bar as it is
Here is the custom tab bar component
const TabBarComponent = (props) => (<BottomTabBar {...props} />)
Here is the tab bar options
{
tabBarComponent: props => {
return (
<View style={{
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
}}>
<TabBarComponent {...props} />
</View>
)
},
tabBarOptions: {
style: {
borderTopWidth: 0,
backgroundColor: '#FFFFFF',
borderTopRightRadius: 20,
borderTopLeftRadius: 20,
height: 55,
paddingBottom: 5,
}
},
initialRouteName: 'HomeScreen',
}
And the final result
position: 'absolute' is a solution for this, but you may notice it'll not look perfectly with the android side, however working perfectly for the android side.
Finally, I found the solution to this after long hard work.
elevation: 0
Set this on tab bar style will fix this issue.
Example -
tabBarOptions={{
showIcon: true,
showLabel: true,
activeTintColor: COLORS.tabSelected,
inactiveTintColor: COLORS.tabNormal,
style: {
backgroundColor:'transparent',
borderTopWidth: 0,
position: 'absolute',
elevation: 0 // <-- this is the solution
},
labelStyle: {
fontSize: 12,
},
}}>
Here are the output screenshots.
A lot of the answers here seem to be a little convoluted for the question. So for others looking how to do so, here's a simple answer:
Within the tab bar options change position to absolute and background colour to transparent such that it looks like:
tabBarOptions: {
style: {
backgroundColor: 'transparent',
position: 'absolute',
left: 0,
bottom: 0,
right: 0
}
}
This is how I solved this for react-navigation v6
import {
createBottomTabNavigator,
BottomTabBar,
} from '#react-navigation/bottom-tabs';
We need to use BottomTabBar to customize the layout and make it transparent
const Tab = createBottomTabNavigator();
<Tab.Navigator
// Here under tabBar we customize the view and set the bg to transparent
tabBar={props => (
<View style={{ backgroundColor: 'transparent', position: 'absolute', left: 0, bottom: 0, right: 0 }}>
<BottomTabBar {...props} />
</View>
)}>
...
If you do it under
screenOptions={({ route }) => ({
tabBarStyle:{
position:absolute,
...
}
})
}
it doesn't work as excpected
For React Navigation v6, you would want to set up screenOptions on the TabNavigator. (I use it in combination with custom / transparent bottom tab bar).
import {
BottomTabBar,
createBottomTabNavigator,
} from '#react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
<Tab.Navigator
screenOptions={{
tabBarStyle: {backgroundColor: 'blue'},
}}
tabBar={props => {
return (
<View>
<BottomTabBar {...props} />
</View>
);
}}
initialRouteName={SCREEN_NAMES.APP.HOME_TAB}
...
</Tab.Navigator>
Mohammed Tawfik's answer worked for me but I had to import <BottomTabBar>component from react-navigation-tabs instead of suggested react-navigation.
In React Navigation v5
tabBarOptions={{
style: {
borderTopWidth: 0,
backgroundColor: 'transparent',
elevation: 0, // this solved the triangle type view problem in android
},
}}>
actually, It is getting its color from NavigationContainer theme backgroundColor you can give transparent color to NavigationContainer like this
import { NavigationContainer } from "#react-navigation/native";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
const Tab = createBottomTabNavigator();
const theme = { //like this
colors: {
background: "transparent",
},
};
<NavigationContainer theme={theme}>
<Tab.Navigator>
<Tab.Screen component={ComponentA} name="A" />
<Tab.Screen component={ComponentB} name="B" />
</Tab.Navigator>
</NavigationContainer>
The solution is simple, think about all component rendering placing in-app,
header: navigation header
body: app content
footer: tab-bar
In-app all the above three-component have their own specific place to render one after one like position relative(default).
and where you want to show the tab-bar top of the body (ignoring its position and placing), then you have to bring it on top of the body by styling tabbarOption "position: 'absolute'",
now it's working, but one new problem arise, due to position absolute body goes all the way bottom, and some of the body content is hidden behind the tab-bar
to fix that need to add padding or add some dummy with some height as per bottom tab bar inside all body screens.

How to customize headerLeft React Navigation?

How can I customize headerLeft TabNavigator of React Navigation.
Here's one of my screens :
I want to remove the Back from the headerLeft
Is it possible ?
Here's my code :
DetailTabs = TabNavigator({
DetailResult:{
screen:DetailResult,
navigationOptions:{
title:'Detail Penginapan',
headerTitleStyle:{
fontSize:14,
textAlign: "center",
flex: 1,
},
tabBarVisible: false,
headerStyle:{
backgroundColor:'#4A94FB',
borderBottomColor: 'transparent',
},
headerTintColor: 'white'
}
}
})
By default, HeaderBackButton component is used. You can implement it and use it to override the back button styles, press props, for example:
link to docs
import { HeaderBackButton } from '#react-navigation/stack';
//in newer versions use:
//import {HeaderBackButton} from '#react-navigation/elements';
const styles = StyleSheet.create({
custom: {
// Custom styles here
}
});
<Screen
name="Home"
component={HomeScreen}
options={{
headerLeft: (props) => (
<HeaderBackButton
{...props}
style={styles.custom}
onPress={() => {
// Do something
}}
/>
),
}}
/>;
If you want full control, you can use your custom back button component, example:
import { CustomBackButton } from 'path/to/custom/component';
<Screen
name="Home"
component={HomeScreen}
options={{
headerLeft: (props) => (
<CustomBackButton {...props} />
),
}}
/>;
You probably just need to set headerBackTitle to null. Check out the docs for headerLeft for more info.
Like this:
DetailTabs = TabNavigator({
DetailResult:{
screen:DetailResult,
navigationOptions:{
title:'Detail Penginapan',
headerTitleStyle:{
fontSize:14,
textAlign: "center",
flex: 1,
},
tabBarVisible: false,
headerStyle:{
backgroundColor:'#4A94FB',
borderBottomColor: 'transparent',
},
headerTintColor: 'white',
headerBackTitle: null,
}
}
})
Key is to put this code from where the back button is clicked, not in App.js
In sample below, for Icon to work, use import Icon from 'react-native-vector-icons/Feather';
constructor(props) {
super(props);
this.state = {
// what ever
};
this.props.navigation.setOptions({
headerLeft: () => (
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Home')}
>
<Icon style = {{paddingLeft : 10}} name="arrow-left" size={26} color="black" />
</TouchableOpacity>
),
});
}

DrawerNavigator cant set background to transparent whatever I do?

I have spend more than si hours trying to change the background of the DrawerNavigator to transparent without any success.
When I write
when I change it in the main component it works
const MainTabBarDrawer = DrawerNavigator({
Home:{
screen:MainTabNavigator,
},
},{
drawerWidth: 200,
drawerPosition: 'right',
// contentComponent: props => <Text style={{color:'white'}} >text
</Text>,
drawerBackgroundColor: 'yellow',
//backgroundColor:'transparent',
// style: {
// //backgroundColor: 'transparent',
// flex: 1
// },
// contentOptions: {
// style: {
// backgroundColor: 'transparent',
// flex: 1
// }
},
{
style: {
backgroundColor: 'transparent',
flex:1
}
}
)
class App extends Component{
render()
{
return(<MainTabBarDrawer style={{backgroundColor: 'transparent'}}/>)
//return(<Login/>)
}
}
While the above approach will work my layout is much complex and I don't want the drawer to appear in all my views.
So dose any body know If I can change the background of the DrawerNavigator directly without rendering it as a component?
In React Navigation 5, this would be:
<Drawer.Navigator
initialRouteName={...}
drawerContent={...}
drawerStyle={{backgroundColor: 'transparent'}}
>
Add drawerBackgroundColor: "transparent" to drawerConfig.
I think you are looking for drawerContentOptions or drawerStyle of Drawer.Navigator
<NavigationContainer>
<Drawer.Navigator
..........
drawerPosition="left"
drawerContentOptions={{
activeBackgroundColor:"transparent", //here change it
}}
drawerStyle={{backgroundColor: 'transparent'}} //or here
initialRouteName="Splash">
<Drawer.Screen
name="HomePage"
component={StackScreen}
options={{
drawerLabel: () => {return null},
title:null,
drawerIcon: () => {return <AppIconImage/>}
}}
/>
</Drawer.Navigator>
</NavigationContainer>
The issue was fixed since I have updated to the latest version
1.0.0-beta.16
Adding the style backgroundColor: 'transparent' to drawerStyle inside the screenOptions param of Drawer.Navigator worked for me.
import React from 'react';
import {createDrawerNavigator} from '#react-navigation/drawer';
import CustomDrawer from '../components/Drawer';
const Drawer = createDrawerNavigator();
const DrawerNavigator = () => {
return (
<Drawer.Navigator
initialRouteName="Stack"
screenOptions={{
headerShown: false,
drawerStyle: {width: '80%', backgroundColor: 'transparent'}, // Add this.
}}
drawerContent={props => <CustomDrawer {...props} />}>
// Screens that go inside the navigator.
</Drawer.Navigator>
);
};
export default DrawerNavigator;
P.S.: I am using #react-navigation/drawer: ^6.5.0.
For ReactNavigation Version 6.
try
<Drawer.Navigator
initialRouteName={...}
drawerContent={...}
screenOptions={{
drawerStyle: {
backgroundColor: 'transparent',
},
}}>
Adding React Docs link for reference.
https://reactnavigation.org/docs/drawer-navigator#drawerstyle

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

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,
}}
>