Repository navigation
fix: ignore a system bar hidden through the system UI visibility on Android 6-10 - #785
Open
YevheniiKotyrlo wants to merge 2 commits into
Open
YevheniiKotyrlo wants to merge 2 commits into
YevheniiKotyrlo wants to merge 2 commits into
Conversation
…ndroid 6-10 On API 23-29 a bar hidden through SYSTEM_UI_FLAG_FULLSCREEN or SYSTEM_UI_FLAG_HIDE_NAVIGATION keeps its system window inset under SYSTEM_UI_FLAG_LAYOUT_STABLE, so a hidden status bar still counted as the top inset and a hidden navigation bar as the bottom one. A hidden bar now leaves only the display cutout, as getInsets does from API 30.
|
@YevheniiKotyrlo is attempting to deploy a commit to the appandflow Team on Vercel. A member of the Team first needs to authorize it. |
Author
YevheniiKotyrlo
marked this pull request as ready for review
October 14, 2026 11:36
YevheniiKotyrlo
marked this pull request as draft
October 15, 2026 16:54
In split-screen and freeform mode Android 7-10 keeps the system bars visible whatever the app requested, and Android 7-9 lays the app out under them, so a status bar hidden through SYSTEM_UI_FLAG_FULLSCREEN still covers the top of the window there. While a flag hides a bar, ask the activity whether it is in multi-window mode, and keep the bars' insets when it is. The question is a binder call, so an app hiding no bar never asks it.
YevheniiKotyrlo
marked this pull request as ready for review
October 15, 2026 18:27
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Summary
On Android 6–10, a status bar hidden through
View.SYSTEM_UI_FLAG_FULLSCREENstill counts as the top inset. That is whatWindowInsetsControllerCompat.hide(statusBars())sets below API 30, and so what React Native'sStatusBar.setHidden(true)does in an edge-to-edge app. The edge-to-edge layout setsSYSTEM_UI_FLAG_LAYOUT_STABLE, under which the system window insets keep a hidden bar's size, andgetRootWindowInsetsCompatMreadssystemWindowInsetTop. SoSafeAreaViewanduseSafeAreaInsets()reserve a band no bar covers. From API 30,getInsets(statusBars() | displayCutout() | …)already excludes a hidden bar. A navigation bar hidden throughSYSTEM_UI_FLAG_HIDE_NAVIGATIONhas the same defect at the bottom (#63).The API 23–29 path now reads
rootView.windowSystemUiVisibility: a hidden status bar leaves the top to the display cutout's safe inset, and a hidden navigation bar leaves the sides and the bottom to it, matching the API 30 path. In split-screen and freeform mode the system keeps the bars visible whatever the app requested, so while a flag hides a bar the activity is asked whether it is in multi-window mode, and if it is the bars keep their insets. That question is a binder call, so an app hiding no bar never asks it.getSafeAreaInsetsgains an overload taking the activity's context, whichSafeAreaContextModuleuses for the initial metrics, because a decor view's own context does not lead to the activity.androidx core's
WindowInsetsCompatreads the same flags below API 30 from 1.16.0 (androidx/androidx@deb2c56), but this library declares no androidx core version, so calling it would tie the result to whichever version an app resolves.Test Plan
SafeAreaUtilsTest(Robolectric, API 29) covers a hidden status bar with and without a display cutout, a visible status bar, a hidden navigation bar, both bars hidden in multi-window mode, a decor view given its activity, and an app hiding no bar never asking about multi-window mode. Onmainthe three hidden-bar cases fail, e.g.expected:<EdgeInsets(top=0.0, right=0.0, bottom=126.0, left=0.0)> but was:<EdgeInsets(top=96.0, right=0.0, bottom=126.0, left=0.0)>. It runs from the example app:cd example/android && ./gradlew :react-native-safe-area-context:testDebugUnitTest. The example's Jetifier skipsbcprov-jdk18on, which Robolectric pulls and whose Java 25 classes Jetifier cannot read, and the package'sfilesandscripts/check-package.mjskeepandroid/src/testout of the npm package.SafeAreaViewunder a hidden status bar reserves a 72 px band on 5.10.1 and none with this change; in split-screen, where the system keeps the status bar visible, the 72 px inset stays as on 5.10.1 (device evidence).assembleDebugwith-PnewArchEnabled=falseandtruepasses on Ubuntu (JDK 17) and Windows.