react-native-safe-area-context icon indicating copy to clipboard operation
react-native-safe-area-context copied to clipboard

SafeAreaView adds extra padding on top inside of react-navigation Stack Navigaor

Open johnryan opened this issue 4 years ago • 12 comments

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:

Screen Shot 2021-01-09 at 10 03 39 AM

See Snack Example here: https://snack.expo.io/vQy4leRbe

johnryan avatar Jan 09 '21 15:01 johnryan

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>

robertjcolley avatar Jan 11 '21 22:01 robertjcolley

@NS-BOBBY-C you've saved my evening, thanks, it fixes the issue for me!

ivankdev avatar Mar 09 '21 22:03 ivankdev

Same issue here! This is happening only in IOS. Screenshot 2021-06-03 at 3 09 18 PM

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

joartola avatar Jun 03 '21 18:06 joartola

Same here. Has it been fixed? Thanks!

Razorholt avatar Jul 16 '21 16:07 Razorholt

I solved it with: <SafeAreaView edges={['bottom', 'left', 'right']} style={{ flex: 1 }}>...</SafeAreaView>

MaiconGilton avatar Jul 20 '21 18:07 MaiconGilton

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!!!

likeSo avatar Aug 27 '21 09:08 likeSo

With me the problem is on Android Nexus, if i put SafeAreaView the android add extra padding on top when i do navigation

brunolcarlos avatar Sep 13 '21 17:09 brunolcarlos

+1

Using the standard SafeAreaView from react-native doesn't exhibit the same behavior. In my case <SafeAreaView edges={["top"]} > did the trick

superandrew avatar Oct 05 '21 06:10 superandrew

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>

DJFriar avatar Feb 07 '22 03:02 DJFriar

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>
  );
}

emeraldsanto avatar Feb 07 '22 15:02 emeraldsanto

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

SabrinaSEDDIK avatar Apr 12 '22 22:04 SabrinaSEDDIK

Thanks <SafeAreaView edges={['top', 'left', 'right']} style={{backgroundColor: COLORS.white, flex: 1}}>

  This did the trick for me!

Bsingh2697 avatar Jul 29 '22 18:07 Bsingh2697

@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;

Bej-Technologies avatar Nov 21 '22 12:11 Bej-Technologies

It's not an issue with this library. Open an issue with react-navigation

jacobp100 avatar Jan 19 '23 16:01 jacobp100

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 :)

JoeSlain avatar Jan 14 '24 23:01 JoeSlain