Skip to content

[iOS] Native Stack layout shift, initial render doesn't take header into account #1779

@dylancom

Description

@dylancom

Description

On initial render the View within a Native Stack has an incorrect height. Upon a second render the height is corrected by taking the header into account. This causes a layout jump/shift which becomes noticable if you are vertically centering your content. Sometimes rendering happens so fast that you don't see it but in other cases it's noticable.

Caused by vc.edgesForExtendedLayout = UIRectEdgeNone; being applied after the first render.
(introduced by: https://github.com/software-mansion/react-native-screens/pull/222/files)
On for e.g. an iPhone 14 Pro the initial height is 773, which becomes 675.3333129882812 after taking into account "UIRectEdgeNone".

Expected behavior: no layout shift. The View should directly get a correct height or only be shown after the corrected height was calculated.

First render (vertically centered incorrectly) Second render
Scherm­afbeelding 2023-06-06 om 20 03 06 Scherm­afbeelding 2023-06-06 om 20 03 21

Steps to reproduce

import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen({ navigation }) {
  const [initialHeight, setInitialHeight] = React.useState(0);
  const [correctedHeight, setCorrectedHeight] = React.useState(0);

  return (
    <View
     onLayout={event => {
      const {x, y, width, height} = event.nativeEvent.layout;
      if (!initialHeight) {
        setInitialHeight(height)
      } else {
        setCorrectedHeight(height)
      }
     }}
     style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{ fontSize: 20, lineHeight: 20 * 1.6, textAlign: 'center' }}>
        Initial height: <Text style={{ fontWeight: 'bold' }}>{initialHeight}</Text>{`\n`}
        Corrected height: <Text style={{ fontWeight: 'bold' }}>{correctedHeight}</Text>
      </Text>
    </View>
  );
}

const Stack = createNativeStackNavigator();

function MyStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={HomeScreen} />
    </Stack.Navigator>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <MyStack />
    </NavigationContainer>
  );
}

Snack or a link to a repository

https://snack.expo.dev/zxQpf-O7e?platform=ios

Screens version

3.20.0

React Native version

0.71.6

Platforms

iOS

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Paper (Old Architecture)

Build type

Debug mode

Device

iOS simulator

Device model

iPhone 14 Pro

Acknowledgements

Yes

Metadata

Metadata

Assignees

Labels

Platform: iOSThis issue is specific to iOSRepro providedA reproduction with a snack or repo is provided

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions