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

SafeAreaView adds extra padding with headerMode='none' in react-navigation nested navigator

Open IngyuTae opened this issue 5 years ago • 7 comments

It works with react-native's SafeAreaView as expected but I'm not sure it is on purpose.

SafeAreaView

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */

import React from 'react';

import {Text} from 'react-native';
import {SafeAreaProvider, SafeAreaView} from 'react-native-safe-area-context';

import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';

const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();

const HomeScreen = () => {
  return (
    <SafeAreaView
      style={{flex: 1, backgroundColor: 'yellow', justifyContent: 'flex-end'}}>
      <Text>justifyContent: 'flex-end'</Text>
    </SafeAreaView>
  );
};

const BottomTab = () => {
  return (
    <Tab.Navigator tabBarOptions={{tabStyle: {backgroundColor: 'red'}}}>
      <Tab.Screen name="Home" component={HomeScreen} />
    </Tab.Navigator>
  );
};

const HomeStack = () => {
  return (
    // if headerMode = "none", extra padding is added at the bottom
    <Stack.Navigator headerMode="none">
      <Stack.Screen name="BottomTab" component={BottomTab} />
    </Stack.Navigator>
  );
};

const App = () => {
  return (
    <SafeAreaProvider>
      <NavigationContainer>
        <HomeStack />
      </NavigationContainer>
    </SafeAreaProvider>
  );
};

export default App;
{
  "dependencies": {
    "@react-native-community/masked-view": "^0.1.10",
    "@react-navigation/bottom-tabs": "^5.8.0",
    "@react-navigation/native": "^5.7.3",
    "@react-navigation/stack": "^5.9.0",
    "react": "16.13.1",
    "react-native": "0.63.2",
    "react-native-gesture-handler": "^1.8.0",
    "react-native-reanimated": "^1.13.0",
    "react-native-safe-area-context": "^3.1.7",
    "react-native-screens": "^2.10.1"
  }
}

IngyuTae avatar Sep 13 '20 15:09 IngyuTae

I have the same issue. It adds a small amount of blank space above the tab bar. And so my child views can't be full height which looks jarring.

Would be great if anyone knows a fix for this.

Reizar avatar Oct 02 '20 02:10 Reizar

I am having the same issue. It is adding space both above and below when using SafeAreaView when header mode is none. You can see the highlighted content is what is wrapped by the SafeAreaView, and how there is extra space between that and the main content.

Screen Shot 2020-10-09 at 4 26 32 PM

jneterer avatar Oct 09 '20 20:10 jneterer

This seems to be the solution:

https://github.com/th3rdwave/react-native-safe-area-context/issues/107#issuecomment-652616230

ajaykumar97 avatar Oct 22 '20 07:10 ajaykumar97

You gotta nest every single route component in a SafeAreaProvider.

E.g.

const HomeScreen = () => {
  return (
    <SafeAreaProvider style={{flex:1}}>
      <SafeAreaView
        style={{flex: 1, backgroundColor: 'yellow', justifyContent: 'flex-end'}}>
        <Text>justifyContent: 'flex-end'</Text>
      </SafeAreaView>
    </SafeAreaProvider>
  );
};

jacobp100 avatar Oct 30 '20 22:10 jacobp100

@jacobp100 thanks for your response, however that is not the issue. The issue is when using two SafeAreaView's, one for the top and bottom of the screen.

@ajaykumar97 I believe I tried that and it did not work, but I will give it a go again.

jneterer avatar Oct 30 '20 22:10 jneterer

@jneterer The SafeAreaProvider will set the safe area for all child SafeAreaViews. If the top SafeAreaProvider does not extend into the bottom safe area (or bottom SAP doesn't extend into the top SA), it will not set bottom safe area insets on any of the child SafeAreaViews.

jacobp100 avatar Oct 30 '20 22:10 jacobp100

here's my workaround using custom hook

import { useSafeAreaInsets } from 'react-native-safe-area-context';

import { useNavigation } from '@react-navigation/native';

import { nestedNavigationProp, stackNavigationProp } from '../app/rootNavigation';

const useSafeArea = () => {
  const navigation = useNavigation<stackNavigationProp | nestedNavigationProp>();
  const insets = useSafeAreaInsets();

  const navState = navigation.dangerouslyGetParent()?.dangerouslyGetState();

  return { ...insets, bottom: navState?.type === 'tab' ? 0 : insets.bottom };
};

export default useSafeArea;

IngyuTae avatar Oct 30 '20 23:10 IngyuTae