Repository navigation
Conversation
Compose ends a drag's scroll before the snap fling starts its own, so the pager saw isScrollInProgress false on DragInteraction.Stop and reported idle as the finger lifted. Report settling on every drag stop, and idle only once nothing is scrolling a frame later. Fixes callstack#1199 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
The frame-dependent state transitions warrant final human validation of cancellation and interrupted-gesture behavior.
No open issues 🎉
What changed in this PR
Fixes #1199 by adjusting Android pager scroll-state reporting so a swipe remains settling until the page stops, rather than reporting idle when the finger lifts. iOS is unchanged.
Changes:
- Report
settlingwhen a drag ends and defer the final rest check by one frame. - Add an example screen displaying state transitions and the scroll offset at
idle. - Add Android regression tests for swipe and programmatic
setPagetransitions.
| File | Description |
|---|---|
example/src/gh-issues/Issue1199ScrollStateRepro.tsx |
Adds an interactive scroll-state reproduction screen. |
example/src/App.tsx |
Registers the new reproduction screen. |
e2e/tests/issues/issue-1199-scroll-state.e2e.ts |
Tests swipe and setPage state sequences. |
android/src/main/java/com/reactnativepagerview/ComposePagerView.kt |
Adjusts drag-end reporting and delays idle detection. |
Review effort: Balanced
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.
Summary
Fixes #1199.
On Android, a swipe reports
onPageScrollStateChangedidleas soon as the finger lifts, while the page is still snapping. It never reportssettling.onPageScrollkeeps firing for another ~150–300 ms afteridle. Anything that treatsidleas "the pager has stopped" acts too early.In Bluesky, the feed tab bar stops following the pager at
idle. With 9.x it froze wherever the finger was lifted (videos in bluesky-social/social-app#12195).What happened
ComposePagerViewdecided betweensettlingandidleonDragInteraction.Stop, usingpagerState.isScrollInProgress.scroll {}before the fling that snaps the pager starts its own.DragGestureNodereturns fromdrag {}, emitsDragInteraction.Stop, and only then doesScrollableNode.onDragStoppedlaunch the fling in a new coroutine. SoisScrollInProgressis always false when the Stop is collected, and every swipe reportsidle.isScrollInProgresscollector sendsidleagain, but it's dropped as a duplicate.onPageScroll(settledPage, 0)andidlemid-gesture.Fix
DragInteraction.StopandCancelreportsettling. A drag always ends in a fling that snaps to a page, even when released at rest.isScrollInProgressturns false, the collector waits one frame. It sends the finalonPageScroll(settledPage, 0)andidleonly if nothing is scrolling by then, so the gap between drag and fling no longer counts as coming to rest.dragging→settling→idle, like 8.x did.setPagestill reportssettling→idle, withidleone frame later than before.settling→dragging.onPageSelectedis unchanged.Test Plan
What's required for testing (prerequisites)?
Android emulator or device.
What are the steps to reproduce (after prerequisites)?
This adds
Issue #1199 Scroll State Reproto the example app, ande2e/tests/issues/issue-1199-scroll-state.e2e.ts. The status line lists the states since the previousidle, and whether the lastonPageScrolloffset was 0 whenidlearrived.setPage(1):settling > idle | idle at rest: yes. This is a control and is the same before and after.dragging > idle | idle at rest: no. After:dragging > settling > idle | idle at rest: yes.Verified
typecheck,format:check,lint(no new warnings) and the e2etypecheckpass.main, the swipe test fails withdragging > idle | idle at rest: noand the control passes. With the fix, both pass. Pixel 9 emulator, Android 16 (API 36), arm64, release build.setPage.dragging→settling→idle, and nothing was left insettling.onPageScrollwith a fractional offset arrived afteridle.main,settlingnever appeared once in dozens of swipes.iOS is untouched.
Compatibility
Checklist
🤖 Generated with Claude Code