Skip to content

fix(Android, Stack): Prefer consuming the top inset from DecorView#3500

Closed
t0maboro wants to merge 1 commit intomainfrom
@t0maboro/consume-top-inset-from-decor-view-for-toolbar
Closed

fix(Android, Stack): Prefer consuming the top inset from DecorView#3500
t0maboro wants to merge 1 commit intomainfrom
@t0maboro/consume-top-inset-from-decor-view-for-toolbar

Conversation

@t0maboro
Copy link
Copy Markdown
Contributor

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

  • Added logic for preferring top inset from DecorView.

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

  • Included code example that can be used to test this change
  • Ensured that CI passes

Copy link
Copy Markdown
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@faljabi
Copy link
Copy Markdown

faljabi commented Dec 31, 2025

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:
Apps using edge-to-edge mode (via react-native-edge-to-edge or native implementation)
Modal presentations (presentation: 'modal' or 'containedModal')
Any screen where insets are consumed by parent views before reaching the toolbar
Evidence:
Version 4.18.0: Works correctly because resolveInsetsOrZero() defaults to using rootWindowInsets
Version 4.19.0: Broken because it only uses consumed/unhandled insets passed down the hierarchy
The Solution: PR #3500 correctly addresses this by preferring DecorView insets as the source of truth for top insets, which are never consumed regardless of the view hierarchy.

Hope this helps.

@andreialecu
Copy link
Copy Markdown

I can confirm we also encountered the issue in #3499, and this PR fixes it (applied via patch-package).

esimkowitz added a commit to esimkowitz/karakeep that referenced this pull request Mar 11, 2026
…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.
@esimkowitz
Copy link
Copy Markdown

esimkowitz commented Mar 16, 2026

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.

MohamedBassem pushed a commit to karakeep-app/karakeep that referenced this pull request Apr 9, 2026
* 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
Ahmed-Abdel-karim pushed a commit to Ahmed-Abdel-karim/karakeep that referenced this pull request Apr 11, 2026
…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
@kkafar
Copy link
Copy Markdown
Member

kkafar commented Apr 14, 2026

@t0maboro Is this PR still relevant in the light of recent changes?

@t0maboro
Copy link
Copy Markdown
Contributor Author

I think it's fine to close this one, falling back to decor view insets was added here:

val topInset = getDecorViewTopInset(decorView)

@t0maboro t0maboro closed this Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No top insets for Android in 4.19.0

5 participants