reactjsreact-nativeexpoexpo-routersafeareaview

Expo Router: how to override default SafeAreaProvider in ExpoRoot?


Framework used: Expo SDK Version: ~49.0.13

Hi everyone,

I’m asking here for help using the new Expo Router v2 with Expo SDK 49. As stated by the team in this blog post, the default layout of the new router is now using a safe area view. The ExpoRoot.txs file below uses a SafeAreaProvider:

export function ExpoRoot({
  wrapper: ParentWrapper = Fragment,
  ...props
}: ExpoRootProps) {
  /*
   * Due to static rendering we need to wrap these top level views in second wrapper
   * View's like <GestureHandlerRootView /> generate a <div> so if the parent wrapper
   * is a HTML document, we need to ensure its inside the <body>
   */
  const wrapper: ExpoRootProps["wrapper"] = ({ children }) => {
    return (
      <ParentWrapper>
        <GestureHandlerRootView>
          <SafeAreaProvider
            // SSR support
            initialMetrics={INITIAL_METRICS}
          >
            {children}

            {/* Users can override this by adding another StatusBar element anywhere higher in the component tree. */}
            {!hasViewControllerBasedStatusBarAppearance && (
              <StatusBar style="auto" />
            )}
          </SafeAreaProvider>
        </GestureHandlerRootView>
      </ParentWrapper>
    );
  };

For my specific use case, I would like to avoid using the SafeAreaProvider here to have a full background color on the screen and use my own paddings and margins in my layout. How can I achieve this without modifying directly this file?

Thanks for your help


Solution

  • I think you already have what you want.

    ExpoRoot inspect

    When inspecting elements using the developer menu, you can observe the margins and paddings applied to your UI components. It's worth noting that, in general, the SafeAreaProvider does not introduce padding or margins itself.

    However, if you want to take control over the safe area insets, you can use the SafeAreaView component and the useSafeAreaInsets hook. By using SafeAreaView, you can ensure that your app's content is correctly adjusted to accommodate the safe areas (e.g., notches and system bars) on the device. You can obtain the specific values for these insets using the useSafeAreaInsets hook.

    For testing purposes, you can create a new stack within your app, typically at the root or layout level, especially if you're using a tab-based template. This stack can be customized to handle the safe areas in your desired way, ensuring that your UI components respect the device's safe area without compromising your design.

    For creating example like this follow steps below

    First if you installed template remove default layout wrappers and create a new stack with these options:

    <Stack.Screen name="index" options={{  headerShown: false,statusBarTranslucent:true ,statusBarHidden:false,navigationBarHidden:true, }} />
    

    And create component for this stack like this:

    import { StyleSheet, View ,Text} from 'react-native';
    import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
    
    export default function Home() {
    const insets =useSafeAreaInsets()
    
    return (<SafeAreaView style={{
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor:"blue",
    padding:0,
    margin:0,
    top:0, // 0-insets.top and use dimentions.screen.height for height
    bottom:0,
    }}><View style={styles.container} >
      <Text style={styles.title}>Screeen</Text>
      <Text>Top: {insets.top}</Text>
      <Text>Bottom: {insets.bottom}</Text>
      <Text>Left: {insets.left}</Text>
      <Text>Right: {insets.right}</Text>
    </View></SafeAreaView>);
    }
    
    const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor:"green",
        padding:0,
        margin:0,
        top:0,
        bottom:0
      }
     });`