Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Content doesn't render under navigation bar on first launch, but corrects itself after backgrounding #45

Closed
3 tasks done
doughsay opened this issue Nov 13, 2024 · 5 comments
Assignees
Labels
bug Something isn't working

Comments

@doughsay
Copy link

doughsay commented Nov 13, 2024

Before submitting a new issue

  • I tested using the latest version of the library, as the bug might be already fixed.
  • I tested using a supported version of react native.
  • I checked for possible duplicate issues, with possible answers.

Bug summary

When you first launch the app, the navigation bar is opaque and content does not render under it. If you background the app, and then open it again, then content is rendered under it.

I've created a minimal Expo 52 app to show this. The content I'm trying to render under the navigation bar is the expo router tab bar, and a formsheet modal.

I've also recorded video demonstrating the issue:
rn-edge-to-edge.webm

Library version

1.1.1

Environment info

System:
  OS: Linux 6.9 Pop!_OS 22.04 LTS
  CPU: (16) x64 AMD Ryzen 7 7800X3D 8-Core Processor
  Memory: 11.11 GB / 30.50 GB
  Shell:
    version: 3.3.1
    path: /usr/bin/fish
Binaries:
  Node:
    version: 22.11.0
    path: ~/.asdf/installs/nodejs/22.11.0/bin/node
  Yarn:
    version: 1.22.19
    path: ~/.yarn/bin/yarn
  npm:
    version: 10.9.0
    path: ~/.asdf/plugins/nodejs/shims/npm
  Watchman:
    version: 4.9.0
    path: /usr/bin/watchman
SDKs:
  Android SDK:
    API Levels:
      - "30"
      - "31"
      - "33"
      - "34"
      - "35"
    Build Tools:
      - 29.0.2
      - 30.0.2
      - 30.0.3
      - 31.0.0
      - 33.0.0
      - 34.0.0
      - 35.0.0
      - 35.0.0
    System Images:
      - android-30 | Google Play Intel x86 Atom
      - android-33 | Google Play Intel x86_64 Atom
      - android-34 | Google Play Intel x86_64 Atom
      - android-35 | Google Play Intel x86_64 Atom
    Android NDK: Not Found
IDEs:
  Android Studio: AI-242.23339.11.2421.12550806
Languages:
  Java:
    version: 22.0.2
    path: /home/chris/.asdf/shims/javac
  Ruby: Not Found
npmPackages:
  "@react-native-community/cli":
    installed: 15.1.2
    wanted: latest
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.76.1
    wanted: 0.76.1
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found

Steps to reproduce

  1. Launch the reproduction app I've provided
  2. See that the tab bar and form sheet modal are not rendered behind the navigation bar
  3. background the app (don't close it)
  4. open the app again
  5. see that the tab bar and form sheet modal are properly rendered behind the navigation bar now

Reproducible sample code

Repo is here: https://github.com/doughsay/expo-edge-to-edge

@doughsay doughsay added the bug Something isn't working label Nov 13, 2024
@zoontek
Copy link
Owner

zoontek commented Nov 13, 2024

react-native-edge-to-edge is correctly setting edge-to-edge each time the android activity is resumed (included at start), the issue here is react-native-screens that restore the system bars.

Until this PR is merged, you need to add statusBarTranslucent and navigationBarTranslucent, or react-native-screens breaks edge-to-edge:

export default function RootLayout() {
  return (
    <ThemeProvider value={DefaultTheme}>
      <Stack
        screenOptions={{
          // You need to add this
          statusBarTranslucent: true,
          navigationBarTranslucent: true,
          navigationBarColor: "transparent",
          statusBarBackgroundColor: "transparent",
        }}
      >
        <Stack.Screen
          name="(tabs)"
          options={{
            headerShown: false,
          }}
        />

        <Stack.Screen
          name="modal"
          options={{
            presentation: "formSheet",
            sheetAllowedDetents: "fitToContents",

            // You need to add this
            statusBarTranslucent: true,
            navigationBarTranslucent: true,
            navigationBarColor: "transparent",
            statusBarBackgroundColor: "transparent",
          }}
        />
      </Stack>
    </ThemeProvider>
  );
}

And even with that, it blinks and sometimes, it doesn't apply the navigation bar color (one time out of two, looks like a race condition):

Screen.Recording.2024-11-13.at.09.38.02.mov

I will work on a patch for react-native-screens (using patch-packages) to avoid this behavior until they fix it. If an app is started in edge-to-edge, they don't have to restore system bars.

@zoontek
Copy link
Owner

zoontek commented Nov 13, 2024

@doughsay Opening the same issue on their repository could be a good idea, as the issue come from there.

EDIT: Got it! It's not directly in react-native-screens, but actually in expo-router. Opening a PR.
EDIT 2: Here is the PR: expo/expo#32854. Until this is fixed, you can patch the package to delete this and this lines.

To explain the race condition in the video / my suspicions about react-native-screens:

  • react-native-edge-to-edge applies edge-to-edge immediately at app start
  • The JS is loaded and ran
  • expo-router mount a StatusBar component that disable edge-to-edge
  • But at approximately the same time, we apply statusBarTranslucent / navigationBarTranslucent with react-native-screens, and it's restoring edge-to-edge. Explaining why it worked one time out of two (which one is applied last)

@doughsay
Copy link
Author

Amazing, thank you so much for digging into this, I wouldn't have been able to figure all that out 😅.

I'll keep an eye on that expo-router issue and in the meantime I'll apply your suggested patch. Thanks!

brentvatne pushed a commit to expo/expo that referenced this issue Nov 13, 2024
# Why

Currently, `expo-router` is mounting react-native `StatusBar`
components, at init they call [this
line](https://github.com/facebook/react-native/blob/v0.76.1/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/WindowUtil.kt#L59),
and it disables [edge-to-edge
display](https://developer.android.com/develop/ui/views/layout/edge-to-edge).

Related issue:
zoontek/react-native-edge-to-edge#45

# How

I added `react-native-is-edge-to-edge` to detect if edge-to-edge is
enabled, prevent the `StatusBar` use when this is the case. People are
expected to use the package `SystemBars` component, which doesn't suffer
from this issue.

There's also no need for `AutoStatusBar` when the package is installed,
as this is the default theme (`Theme.EdgeToEdge`) behavior.

# Test Plan

- Create an expo project with `expo-router`
- Add `react-native-edge-to-edge`, start the app
- Apply the fix
- Rebuild, restart the app
@zoontek
Copy link
Owner

zoontek commented Nov 13, 2024

@doughsay expo-router 4.0.5 has been released with the fix, could you try it?

@doughsay
Copy link
Author

Yep, it works! Thanks a lot for such a quick turnaround!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants