Skip to content

Fix Android MVCP anchor selection when z-index reorders children - #57959

Open
hsource wants to merge 1 commit into
react:mainfrom
wanderlog:harry-mvcp
Open

Fix Android MVCP anchor selection when z-index reorders children#57959
hsource wants to merge 1 commit into
react:mainfrom
wanderlog:harry-mvcp

Conversation

@hsource

@hsource hsource commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary:

Motivation

At Wanderlog, we use a FlatList with negative zIndex so earlier items' bottom shadows can cover later items (by default, later items cover earlier items).

When maintainVisibleContentPosition is enabled on Android, computeTargetView selects the scroll anchor by scanning content children and picking the first one whose end position exceeds the current scroll offset. Fabric can reorder native children when views use zIndex, so hierarchy order no longer matches layout order. In that case the helper can anchor to the wrong item, and scroll corrections keep the bottom edge of the visible content fixed instead of the top.

Fix

This change scans all eligible children and selects the topmost visible anchor (the smallest end position still below the scroll offset). It also clears the cached anchor when the helper stops listening.

Ported from the approach in #46247, adapted for the current Kotlin helper, and simplified.

Changelog:

[ANDROID] [FIXED] - Fix maintainVisibleContentPosition anchoring to the wrong child when z-index reorders Fabric children

Test Plan:

Manual test on Android using RNTester:

  1. Open ScrollViewsmooth bi-directional content loading
  2. Add a few items and scroll so there are items above and below the current item
  3. Use Change height at id to change the height of an item in the middle
  4. Verify the top edge of that item stays in place, rather than the bottom edge jumping
Before (maintained position relative to bottom) After (correctly maintains position relative to top)
Before edited After edited

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 14, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Aug 14, 2026
When Fabric reorders scroll content children due to z-index, the old
computeTargetView logic picked the first child in hierarchy order whose
end position exceeded the scroll offset. That could anchor to the wrong
item, so height changes kept the bottom edge fixed instead of the top.

Scan all children and select the topmost visible anchor instead. Extend
the RNTester AppendingList example with negative z-index values and a
"Change height at id" control to reproduce the bug.

Test plan (Android):
1. Open RNTester → ScrollView → "smooth bi-directional content loading"
2. Add a few items and scroll so there are items above and below the
   current item
3. Use "Change height at id" to change the height of an item in the
   middle
4. Verify the top edge of that item stays in place, rather than the
   bottom edge jumping

Co-authored-by: Cursor <cursoragent@cursor.com>
paddingBottom?: number,
};

function AppendingList(): React.Node {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This change was made because cloneElement seemed to remove the zIndex, so we instead render items without cloneElement.

While I was at it, I also changed this to a function component.

hsource added a commit to wanderlog/react-native that referenced this pull request Aug 14, 2026
This patch should not be needed once react#57959 is merged.

When Fabric reorders scroll content children due to z-index, the old
computeTargetView logic picked the first child in hierarchy order whose
end position exceeded the scroll offset. That could anchor to the wrong
item, so height changes kept the bottom edge fixed instead of the top.

Scan all children and select the topmost visible anchor instead. Extend
the RNTester AppendingList example with negative z-index values and a
"Change height at id" control to reproduce the bug.

Test plan (Android):
1. Open RNTester → ScrollView → "smooth bi-directional content loading"
2. Add a few items and scroll so there are items above and below the
   current item
3. Use "Change height at id" to change the height of an item in the
   middle
4. Verify the top edge of that item stays in place, rather than the
   bottom edge jumping

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant