fix(Android, Stack): Prefer consuming the top inset from DecorView#3500
fix(Android, Stack): Prefer consuming the top inset from DecorView#3500
Conversation
kkafar
left a comment
There was a problem hiding this comment.
I don't approve this change right now for at least few reasons.
First - we don't have a valid reproduction, so it's really hard to tell what is the root cause of the issue -> blindly working around it introduces a hard to maintain code into our codebase. We should insist on having reproduction here.
Second - we should avoid using insets directly from window / decor, exactly for this reason -> if someone consumes the insets & sets the padding above us, we will apply the padding erroneously for the second time. This will most likely also break nested stacks scenarios. So I believe now that this is not really a fix, rather a workaround for this particular issue.
Third - likely the bug comes, because somebody (some component, maybe even one of ours) consumes the insets and does not apply correct padding and this is where we should look for the fix.
|
Just to help here, I used claude code to help find the culprit that may help you identify the issue. Find the details below: Root Cause Analysis: The regression was introduced by PR #3240 which changed how CustomToolbar retrieves window insets. The Breaking Change: In CustomToolbar.kt:116-129, the toolbar now uses unhandledInsets from super.onApplyWindowInsets(insets) instead of rootWindowInsets. Why It Fails: In edge-to-edge mode (enforced on Android SDK 35+), parent views in the hierarchy consume window insets before they reach the toolbar. By the time CustomToolbar.onApplyWindowInsets() is called, the top system bar inset has already been consumed, resulting in zero top padding. Affected Scenarios: Hope this helps. |
|
I can confirm we also encountered the issue in #3499, and this PR fixes it (applied via patch-package). |
…inset react-native-screens 4.19.0 (PR #3240) changed CustomToolbar to use ancestor-propagated insets instead of rootWindowInsets. This conflicts with react-native-keyboard-controller's rootView inset listener, which modifies insets before they reach the toolbar, causing the Android header to be too short (missing status bar height). Apply upstream fix from software-mansion/react-native-screens#3500: read the top inset directly from the DecorView instead of relying on ancestor-propagated insets which may have been consumed earlier. This patch can be removed once #3500 is merged and released upstream.
|
I can confirm the bug in 4.19.0 and the patch suggested resolves it. @kkafar I understand your reasoning, but this manifests as a regression, given a lot of libraries with non-rendering providers (i.e. react-native-keyboard-controller) eat insets provided from parents. We can go chase these in a bunch of repos, but maintaining backwards compatibility is really important. I agree that your logic is the "correct" approach and other libraries should be aligning to this, however I would recommend documenting this as a breaking change, with a new option that maintains the old behavior for at least a few releases with a deprecation notice and a CTA to fix behavior in other projects. I'm willing to prepare an updated version of this fix with a feature gate and deprecation notice if you are willing to sign off on it. |
* feat(mobile): add iOS 26 header compatibility Disable headerBlurEffect on iOS 26 where the system provides native Liquid Glass blur. Add isIOS26 constant in lib/ios.ts for platform detection. * fix(mobile): remove excess padding and use theme colors for header right icons Remove px-4 from header right icon wrappers that caused oval-shaped tap targets. Use theme foreground color instead of hardcoded blue/gray for header icons so they match the navigation bar style. * Upgrade react-native-screens to fix icon alignment issue in round iOS 26 right header buttons * fix padding in text header right buttons * fix(mobile): patch react-native-screens 4.19.0 to fix Android header inset react-native-screens 4.19.0 (PR #3240) changed CustomToolbar to use ancestor-propagated insets instead of rootWindowInsets. This conflicts with react-native-keyboard-controller's rootView inset listener, which modifies insets before they reach the toolbar, causing the Android header to be too short (missing status bar height). Apply upstream fix from software-mansion/react-native-screens#3500: read the top inset directly from the DecorView instead of relying on ancestor-propagated insets which may have been consumed earlier. This patch can be removed once #3500 is merged and released upstream. * fix(mobile): patch react-native-keyboard-controller instead of react-native-screens for Android header inset The root cause of the Android header inset bug is in react-native-keyboard-controller, not react-native-screens. When edge-to-edge mode is enabled (Expo 55 default), KeyboardProvider forces statusBarTranslucent=true, and replaceStatusBarInsets() zeroes out the top system bar inset before dispatching to child views. This means react-native-screens' CustomToolbar receives top=0 and applies no status bar padding. The fix: always pass through the real system bar top inset in replaceStatusBarInsets(). The content margin in setupWindowInsets() already handles the layout offset independently. This replaces the previous react-native-screens patch (upstream PR #3500) with a 2-line fix at the actual root cause. Upstream issue: kirillzyusko/react-native-keyboard-controller#1013 Related: kirillzyusko/react-native-keyboard-controller#1292 * fix lockfile
…keep-app#2523) * feat(mobile): add iOS 26 header compatibility Disable headerBlurEffect on iOS 26 where the system provides native Liquid Glass blur. Add isIOS26 constant in lib/ios.ts for platform detection. * fix(mobile): remove excess padding and use theme colors for header right icons Remove px-4 from header right icon wrappers that caused oval-shaped tap targets. Use theme foreground color instead of hardcoded blue/gray for header icons so they match the navigation bar style. * Upgrade react-native-screens to fix icon alignment issue in round iOS 26 right header buttons * fix padding in text header right buttons * fix(mobile): patch react-native-screens 4.19.0 to fix Android header inset react-native-screens 4.19.0 (PR #3240) changed CustomToolbar to use ancestor-propagated insets instead of rootWindowInsets. This conflicts with react-native-keyboard-controller's rootView inset listener, which modifies insets before they reach the toolbar, causing the Android header to be too short (missing status bar height). Apply upstream fix from software-mansion/react-native-screens#3500: read the top inset directly from the DecorView instead of relying on ancestor-propagated insets which may have been consumed earlier. This patch can be removed once #3500 is merged and released upstream. * fix(mobile): patch react-native-keyboard-controller instead of react-native-screens for Android header inset The root cause of the Android header inset bug is in react-native-keyboard-controller, not react-native-screens. When edge-to-edge mode is enabled (Expo 55 default), KeyboardProvider forces statusBarTranslucent=true, and replaceStatusBarInsets() zeroes out the top system bar inset before dispatching to child views. This means react-native-screens' CustomToolbar receives top=0 and applies no status bar padding. The fix: always pass through the real system bar top inset in replaceStatusBarInsets(). The content margin in setupWindowInsets() already handles the layout offset independently. This replaces the previous react-native-screens patch (upstream PR #3500) with a 2-line fix at the actual root cause. Upstream issue: kirillzyusko/react-native-keyboard-controller#1013 Related: kirillzyusko/react-native-keyboard-controller#1292 * fix lockfile
|
@t0maboro Is this PR still relevant in the light of recent changes? |
|
I think it's fine to close this one, falling back to decor view insets was added here: |
Description
The top inset from DecorView is currently used in both Screen and ScreenDummyLayoutHelper to manually apply layout adjustments. To ensure consistent behavior between Screen and Toolbar, we should preferably handle the top inset here. Relying on unhandledInsets may be unreliable, as they could already have been consumed earlier in the layout process.
Fixes: #3499
Changes
Test code and steps to reproduce
I'm not able to reproduce this issue on our side, so I'm basing on the information from: #3499 (comment)
Additionally, I ensured that it causes no regression in Test3006, for which these changes were initially made.
Checklist