fix(scroll): render the first items where initialScrollIndex lands - #2516
Open
anubhavvI2B wants to merge 1 commit into
Open
anubhavvI2B wants to merge 1 commit into
anubhavvI2B wants to merge 1 commit into
Conversation
The progressive first render planned its window from the initial item's own offset, while applyInitialScrollIndex scrolls to that offset plus initialScrollIndexParams.viewOffset, clamped by the ScrollView to its scrollable range. With a negative viewOffset, or an initial item inside the last screen, the items between the viewport edge and the initial item stayed blank until the next render pass. Plan the first render window at the same clamped offset.
anubhavvI2B
force-pushed
the
fix/initial-scroll-first-render-offset
branch
from
September 28, 2026 21:39
9b6826a to
1aa2f32
Compare
Author
|
I have signed the CLA! |
Author
Hey @tobi can you review this once |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Follow-up to #1870.
With
initialScrollIndex, the first items are rendered progressively before the list scrolls.applyInitialScrollAdjustmentplans that first render from the initial item's own offset, butapplyInitialScrollIndexthen scrolls to that offset plusinitialScrollIndexParams.viewOffset, and the ScrollView clamps the result to its scrollable range. When the two differ, the items between the viewport edge and the initial item are not part of the first render and stay blank until the next pass renders the draw-distance buffer:viewOffset(initial item shown lower in the viewport): the rows before the initial item are blank.viewOffset(for examplestartRenderingFromBottom): the list cannot scroll to the item's own offset, so the rows before it are blank.This change plans the first render window at the offset the list actually lands on: the item offset plus
viewOffset, clamped to[-firstItemOffset, getMaxScrollOffset() - firstItemOffset]. Without aviewOffset, and away from the end of the list, the result is unchanged.We hit this in an inverted chat list that opens at a search result with
initialScrollIndexand a negativeviewOffset: the target row painted first and the rows below it stayed white until the buffer pass (about 1 s in a dev build, about 3 s on a cold start). With an equivalent local patch on 2.2.2, the first frame shows the full screen around the target.Reviewers' hat-rack 🎩
applyInitialScrollAdjustmentinRecyclerViewManager.ts. The upper clamp usesgetMaxScrollOffset(), which relies on estimated sizes until items are measured; each progressive pass recomputes it, the same way it recomputes the item offset.viewOffset: only when the initial item is inside the last screen, where the first render now covers that screen instead of starting at the item.Screenshots or videos
None. The three new unit tests cover the cases above.
Test plan
yarn test). The 3 new tests inRecyclerView.test.tsxfail onmainand pass with this change.yarn type-check)viewOffsetcase on an Android emulator in our app, with an equivalent patch on 2.2.2 (applied only whenviewOffsetis set)