react-native-safe-area-context
react-native-safe-area-context copied to clipboard
SafeAreaView adds extra padding on top inside of react-navigation Stack Navigaor
The SafeAreaView appears to be adding extra padding below the Navigation bar when using react-navigation - Note the safe area goes all the way to the top but adds padding below the navigation bar:

See Snack Example here: https://snack.expo.io/vQy4leRbe
We had this same issue. We solved it by using the edges prop - in our case we wanted to disable the bottom, so we made a small wrapper component which looked something like this:
export const CustomSafeAreaView = (props: any) =>
<SafeAreaView edges={['top', 'left', 'right']}>{props.children}</SafeAreaView>
@NS-BOBBY-C you've saved my evening, thanks, it fixes the issue for me!
Same issue here! This is happening only in IOS.
import React from 'react';
import {SafeAreaView} from 'react-native-safe-area-context';
import {View} from 'react-native';
const LoginScreen = () => {
return (
<SafeAreaView style={{backgroundColor: 'green', flex: 1}}>
<View style={{backgroundColor: 'red', flex: 1}} />
</SafeAreaView>
);
};
export default LoginScreen;
"dependencies": { "@react-native-community/masked-view": "^0.1.11", "@react-navigation/native": "^5.9.4", "@react-navigation/stack": "^5.14.5", "react": "17.0.1", "react-native": "0.64.1", "react-native-gesture-handler": "^1.10.3", "react-native-reanimated": "^2.2.0", "react-native-safe-area-context": "^3.2.0", "react-native-screens": "^3.3.0" },
Same here. Has it been fixed? Thanks!
I solved it with:
<SafeAreaView edges={['bottom', 'left', 'right']} style={{ flex: 1 }}>...</SafeAreaView>
I got the same problem on a View that is at the bottom of my screen. It seems like the SafeAreaView applies all of the directions to itself by default. I solved the problem by the edge
prop.
The SafeAreaView
SHOULD ONLY apply safe area insets that it contains, NOT ALL!!!
With me the problem is on Android Nexus, if i put SafeAreaView the android add extra padding on top when i do navigation
+1
Using the standard SafeAreaView from react-native doesn't exhibit the same behavior. In my case
<SafeAreaView edges={["top"]} >
did the trick
Many of the solutions above are only working due to narrow scope (only targeting one platform, or never using a header/always using a header). Here is what I did that is working in my cross platform app where some screens have the header and some do not:
I already have a Screen component that contains the SafeAreaView, so I first set edges to only the left and right sides, and then I extended the Screen component to accept an argument that when present adds the top edge padding as well. I then include this on the screens where I do not have a header.
Here is what my Screen component looks like for reference:
function Screen({ children, style, hasNoHeader }) {
const edges = ['left', 'right']
if (hasNoHeader) {
edges.push('top')
}
return (
<SafeAreaView style={[styles.screen, style]} edges={edges}>
<StatusBar barStyle='light-content' />
<View style={{backgroundColor: settings.statusBarColor, height: 6}} />
<View style={[styles.view, style]}>
{children}
</View>
</SafeAreaView>
);
}
Then in the places where I need the extra padding I just call <Screen hasNoHeader>
To piggyback off of @DJFriar's suggestion, I think a more flexible solution would be to dynamically infer edges
using a few react-navigation
utility functions:
import { useHeaderHeight } from '@react-navigation/stack';
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
export function Screen({ children, ...rest }) {
const headerHeight = useHeaderHeight();
const tabBarHeight = useBottomTabBarHeight();
const edges = ['left', 'right'];
if (headerHeight === 0) edges.push('top');
if (tabBarHeight === 0) edges.push('bottom');
return (
<SafeAreaView {...{ edges }} {...rest}>
{children}
</SafeAreaView>
);
}
As for me, I solved it with a different import I was importing SafeAreaView from "react-native-safe-area-context" I changed it to "react-native" and the extra padding disapeared
Thanks <SafeAreaView edges={['top', 'left', 'right']} style={{backgroundColor: COLORS.white, flex: 1}}>
This did the trick for me!
@emeraldsanto your solution crashes for me if e.g. the view is not inside a screen in Bottom Tab Navigator. For me it works using HeightContext instead:
import { BottomTabBarHeightContext } from '@react-navigation/bottom-tabs';
import { HeaderHeightContext } from '@react-navigation/elements';
import PropTypes from 'prop-types';
import React from 'react';
import { StyleSheet } from 'react-native';
import { SafeAreaView as SAV } from 'react-native-safe-area-context';
const styles = StyleSheet.create({
flex: {
flex: 1,
},
});
const SafeAreaView = ({ children }) => {
const edges = ['left', 'right'];
return (
<HeaderHeightContext.Consumer>
{(headerHeight) => (
<BottomTabBarHeightContext.Consumer>
{(tabBarHeight) => {
if (headerHeight === undefined || headerHeight === 0) {
edges.push('top');
}
if (tabBarHeight === undefined || tabBarHeight === 0) {
edges.push('bottom');
}
return (
<SAV edges={edges} style={styles.flex}>
{children}
</SAV>
);
}}
</BottomTabBarHeightContext.Consumer>
)}
</HeaderHeightContext.Consumer>
);
};
SafeAreaView.propTypes = {
children: PropTypes.oneOfType([
PropTypes.element,
PropTypes.arrayOf(PropTypes.element),
]).isRequired,
};
export default SafeAreaView;
It's not an issue with this library. Open an issue with react-navigation
As for me, I solved it with a different import I was importing SafeAreaView from "react-native-safe-area-context" I changed it to "react-native" and the extra padding disapeared
You have no idea how much mental health you've just saved me. Merci :)