Skip to content

Fix inverted FlatList RefreshControl indicator appearing at visual bottom (#17553) - #57905

Open
kulkarni-rohan wants to merge 1 commit into
react:mainfrom
kulkarni-rohan:fix/17553-inverted-refresh-indicator
Open

Fix inverted FlatList RefreshControl indicator appearing at visual bottom (#17553)#57905
kulkarni-rohan wants to merge 1 commit into
react:mainfrom
kulkarni-rohan:fix/17553-inverted-refresh-indicator

Conversation

@kulkarni-rohan

@kulkarni-rohan kulkarni-rohan commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Fixes #17553

Summary

Problem: FlatList with inverted={true} is used for chat/terminal UIs. It applies transform: [{scaleY: -1}] to the ScrollView and re-flips cells. RefreshControl is a child of inverted ScrollView, so it appears at physical top = visual bottom, while users expect it at visual top.

Root cause: _defaultRenderScrollComponent in VirtualizedList.js passed progressViewOffset without accounting for inversion.

Fix (JS-only, 21 lines, no new API):

  • Auto-calculate progressViewOffset = visibleLength when isInvertedVirtualizedList && props.progressViewOffset==null && visibleLength>0
  • Android SwipeRefreshLayout uses offset to move indicator to visual top (physical bottom = visual top after scaleY:-1)
  • Clone custom refreshControl with offset when needed – improvement over Fix inverted FlatList RefreshControl indicator position #55464 which ignored custom case
  • Guards visibleLength>0 to avoid flicker before layout

Supersedes #55464 (stalled, CI failing) with custom-control hardening.

Changelog:

[General] [Fixed] - Fix inverted FlatList RefreshControl indicator appearing at visual bottom instead of visual top (#17553)

Test Plan

yarn jest packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js --no-coverage --no-watchman
# 87 passed, 1 skipped, 59 snapshots (5 new tests)
# - sets progressViewOffset when inverted and layout known
# - does not set when not inverted
# - respects user-provided offset
# - does not set before layout (visibleLength=0 guard)
# - clones custom refreshControl with offset

yarn lint packages/virtualized-lists/Lists/VirtualizedList.js
# pass

Risks

Low – only affects inverted lists with onRefresh. Non-inverted unchanged. Snapshots still pass.

Known Limitation

Pull gesture still triggers at physical top (visual bottom) because native UIRefreshControl/SwipeRefreshLayout edge is at offset 0. This PR fixes indicator position (main bug title). Full gesture inversion needs native change, tracked separately.

Fixes #17553

…t#17553)

When FlatList is inverted, scaleY: -1 transform causes RefreshControl to appear at visual bottom instead of visual top.

This fix auto-calculates progressViewOffset = visibleLength when inverted and no user offset is provided, moving the Android SwipeRefreshLayout indicator to visual top. Also clones custom refreshControl with offset when needed.

Fixes react#17553
Supersedes react#55464 with custom-control handling.

[GENERAL] [FIXED] - Fix inverted FlatList RefreshControl indicator appearing at visual bottom instead of visual top (react#17553)
@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 12, 2026
@facebook-github-tools facebook-github-tools Bot added p: Facebook Partner: Facebook Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Aug 12, 2026
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. p: Facebook Partner: Facebook Partner 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.

Inverted FlatList displays activity indicator at the bottom

1 participant