Skip to content

fix(Android, Stack): don't add top inset to measured header height when it's disabled#4357

Open
phazei wants to merge 1 commit into
software-mansion:mainfrom
phazei:fix/dummy-header-height-consume-top-inset
Open

fix(Android, Stack): don't add top inset to measured header height when it's disabled#4357
phazei wants to merge 1 commit into
software-mansion:mainfrom
phazei:fix/dummy-header-height-consume-top-inset

Conversation

@phazei

@phazei phazei commented Jul 17, 2026

Copy link
Copy Markdown

Description

When a header opts out of the top inset on Android (disableTopInsetApplication, which sets consumeTopInset = false), the measured header height still includes the status bar / cutout inset, so it comes back too tall.

The native CustomToolbar only pads itself with the top inset when legacyTopInsetBehavior || consumeTopInset is true. But the dummy layout used to report the header height back to the shadow tree always adds the decor view top inset, regardless of that prop. So the height it reports doesn't match what the toolbar actually renders, and the screen content ends up pushed down by roughly the status bar height on the first Fabric layout.

This looks like it was just missed when the disable*InsetApplication props landed in #4220 — the toolbar learned about consumeTopInset but the measurement path didn't.

Changes

  • RNSScreenShadowNode.cpp: read the same header props the toolbar uses (legacyTopInsetBehavior || consumeTopInset) and pass the result down to the measurement as applyTopInset. The JNI signature changes from (IZ)F to (IZZ)F.
  • ScreenDummyLayoutHelper.kt: only add the decor view top inset when applyTopInset is true, and include the flag in the measurement cache key so screens with different settings don't share a stale cached height.

Test plan

Reproducible with the existing Test4220 scenario:

  1. Open Test4220 on Android.
  2. Go to the Details screen and toggle disableTopInsetApplication on.

Before this change the screen content sits about a status bar's height too low (the header reserves space it isn't actually using). After, the content sits directly under the header.

Checklist

  • Included code example that can be used to test this change. (existing Test4220)
  • For visual changes, included screenshots / GIFs / recordings documenting the change.
  • For API changes, updated relevant public types. (no public API change)
  • Ensured that CI passes

…consumeTopInset is false

The C++ dummy-layout measurement (findHeaderHeight -> ScreenDummyLayoutHelper.
computeDummyLayout) unconditionally added the decor view top inset to the reported
header height. The native CustomToolbar, however, only pads itself with the top
inset when `legacyTopInsetBehavior || consumeTopInset` holds (introduced in software-mansion#4220).

As a result, any header that opts out of the top inset via `disableTopInsetApplication`
(consumeTopInset == false) has its measured height over-reported by the status-bar /
cutout inset, offsetting screen content by that amount on the first Fabric layout.

Mirror the toolbar's condition in the measurement path:
- pass `applyTopInset = legacyTopInsetBehavior || consumeTopInset` through JNI
  (computeDummyLayout signature (IZ)F -> (IZZ)F)
- zero the top inset in the dummy measurement when applyTopInset is false
- include applyTopInset in the measurement cache key so mixed-mode headers do not
  collide on a stale cached height

Verify with Test4220: toggling `disableTopInsetApplication` should no longer offset
the screen content below the header.
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.

1 participant