Skip to content

Conversation

@t0maboro
Copy link
Contributor

@t0maboro t0maboro commented Dec 1, 2025

Description

This PR introduces a set of fixes and manual layout adjustments to address layout/content jumps in Fabric. I listed them under Changes section with some motivations.

Caution

This PR aims to resolve the issue only on Fabric; on Paper some additional effort is needed and (potentially) would require adapting ScreenDummyLayoutHelper to old arch. The work will be continued in a separate PR.

Changes

  • Added CustomAppBarLayout: This custom implementation triggers a layout refresh on the AppBarLayout when we apply padding adjustments to the CustomToolbar. AppBarLayout just dispatches insets to Toolbar; therefore, I'm still handling them at the Toolbar level.
  • Ensured early initialization of ActionMenuView in the Toolbar: Initializing the ActionMenuView early in the layout process prevents inconsistencies and avoids fallback to the system default toolbar height in onMeasure, ensuring a consistent layout.
  • Manual shadow offset correction in the Screen: I'm applying some temporary padding corrections at the Screen level until insets are applied.
  • Layout correction for ScreenDummyLayoutHelper: A similar early correction approach is used for ScreenDummyLayoutHelper to keep the consistency for the header size before full layout pass (this one with insets applied) is complete.
  • Added DecorViewInsetHelper: React's layout arrives before insets have been applied, leading to content jumps. To counter this, we rely on insets available from the DecorView (child of RootView). A dedicated helper class extracts these inset values. Additionally, it ensures that the insets are applied only on the topmost Screen with Toolbar, preventing the unnecessary padding on the nested Toolbars.

Screenshots / GIFs

Here you can add screenshots / GIFs documenting your change.

You can add before / after section if you're changing some behavior.

Fabric

Before

Screen.Recording.2025-12-02.at.09.48.27.mov
Screen.Recording.2025-12-02.at.09.49.06.mov

After

Screen.Recording.2025-12-02.at.09.47.01.mov
Screen.Recording.2025-12-02.at.09.46.23.mov

Test code and steps to reproduce

Added Test3006, tested with API levels above and below 30, with both Status Bar and Display Cutout. As mentioned earlier only testing on FabricExample is in the scope of this PR.

Checklist

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

@t0maboro t0maboro marked this pull request as draft December 1, 2025 16:30
@t0maboro t0maboro marked this pull request as ready for review December 2, 2025 10:26
@t0maboro t0maboro changed the title @t0maboro/android fix jumping content fix(Android, Stack, Fabric): Fix jumping content in nested Screen for Fabric Dec 2, 2025
@t0maboro t0maboro changed the title fix(Android, Stack, Fabric): Fix jumping content in nested Screen for Fabric fix(Android, Stack, Fabric): Fix jumping content in nested stack for Fabric Dec 2, 2025
Copy link
Contributor

@kligarski kligarski left a comment

Choose a reason for hiding this comment

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

Did you test how this behaves with fixes from #3405 and nested stacks in general?

@t0maboro
Copy link
Contributor Author

t0maboro commented Dec 3, 2025

Did you test how this behaves with fixes from #3405 and nested stacks in general?

Good callout about 3405 I tested with and without SAV for nested stacks, results look legit

Screen.Recording.2025-12-03.at.10.20.40.mov
Screen.Recording.2025-12-03.at.10.21.46.mov

@t0maboro t0maboro requested a review from kligarski December 3, 2025 09:38
Copy link
Contributor

@kligarski kligarski left a comment

Choose a reason for hiding this comment

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

Looks good & scary at the same time.

@JoniVR
Copy link

JoniVR commented Dec 4, 2025

This resolved all my jumping issues on a rather complex split-view tablet Android application. I have applied these changes as a patch for now. Thanks for this!!

Copy link
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.

Great job here. Looks as hacky as I expected after our initial discussions 😄

Asked few questions & added remarks. Please answer them.

val maybeAppBarLayout = parent as? CustomAppBarLayout
maybeAppBarLayout?.let {
if (shouldApplyLayoutCorrectionForTopInset && !it.isInLayout) {
it.onToolbarLayout(paddingTop)
Copy link
Member

Choose a reason for hiding this comment

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

Reading this I have a problem with naming here. We call onToolbarLayout in requestLayout. This clearly contradicts.

Why do we call this callback in requestLayout? Shouldn't it be called in onLayout?

Copy link
Member

Choose a reason for hiding this comment

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

By doing it this way, we call onToolbarLayout before the layout triggered by this requestLayout call happens. Is this intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

By doing it this way, we call onToolbarLayout before the layout triggered by this requestLayout call happens. Is this intentional?

yes, in CustomAppBarLayout I'm calling layout explicitly to make a correction asap, without any overhead regarding calling requestLayout

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Okay. Can we add comment documenting this? That we call layout here, to ensure immediate frame update & prevent potentially invalid state being displayed before requested layout is executed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@t0maboro t0maboro requested a review from kkafar December 5, 2025 12:23
Copy link
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 followed up with request on the last review.

@t0maboro t0maboro requested a review from kkafar December 5, 2025 14:51
Copy link
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.

Looks good now. Thank you

@t0maboro t0maboro merged commit 9b0be6b into main Dec 5, 2025
5 checks passed
@t0maboro t0maboro deleted the @t0maboro/android-fix-jumping-content branch December 5, 2025 15:00
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.

5 participants