Skip to content

Fix ScrollView drag stutter on Android when the ScrollView moves during a drag - #59574

Draft
tjzel wants to merge 2 commits into
react:mainfrom
tjzel:@tjzel/android/scrollview-stable-touch-coordinates
Draft

tjzel wants to merge 2 commits into
react:mainfrom
tjzel:@tjzel/android/scrollview-stable-touch-coordinates

Conversation

@tjzel

@tjzel tjzel commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Note

This PR description is AI-generated.

Fixes #38470

Summary:

On Android, a ScrollView that moves on screen while it is being dragged stutters, and when it moves faster than the finger it stops scrolling. This happens for example when top or transform follows the scroll offset. android.widget.ScrollView computes the drag delta from view-local touch coordinates, so the view's own movement looks like finger movement in the other direction.

I added StableTouchCoordinatesHelper. It offsets each MotionEvent by how far the view moved on screen since ACTION_DOWN before ReactScrollView and ReactHorizontalScrollView pass it to the platform scroll view and to VelocityHelper. It converts that movement into the view's own axes, so flipped lists (inverted FlatList uses scale: -1 on Android) and scaled ancestors are handled. It adds the ancestors' scroll offsets back, so movement caused by nested scrolling is not compensated twice, because ScrollView already handles it. I also added a MovingScrollViewExample to RNTester.

Changelog:

[ANDROID] [FIXED] - Fix ScrollView stuttering or stopping when the ScrollView moves while it is being dragged

Test Plan:

Recordings from RNTester MovingScrollViewExample on a Pixel 8. Each recording shows the same two drags. Left is before the fix, right is after.

Multiplier 2: before, the list barely scrolls and jumps back.

multiplier 2

Multiplier 1: before, the list scrolls less than the finger moves and stutters.

multiplier 1

MP4 versions: multiplier 2, multiplier 1.

StableTouchCoordinatesHelperTest and the other com.facebook.react.views.scroll unit tests pass.

In RNTester MovingScrollViewExample on an Android 16 emulator, I made one 343 dp drag per run. These are the scroll offsets at ACTION_UP in dp, two runs each (about 330 is correct):

case         multiplier   before      after
top          0            325, 333    319, 328
top          1            200, 150    330, 320
top          2              0,  44    327, 330
translateY   1            205, 182    322, 328
translateY   2             41, 322    335, 331
horizontal   1            177, 183    331, 333
horizontal   2            132, 267    330, 329

Inverted FlatList on a Pixel 8, one 404 dp drag per run (about 404 is correct):

multiplier   before      after
0            414, 413    411, 413
1            713, 715    414, 415
2            713, 715    414, 414

In the nested case (nestedScrollEnabled ScrollView inside a ScrollView), outer + inner scroll was 336 and 326 dp before and 335 and 316 dp after.

@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 Oct 28, 2026
@facebook-github-tools facebook-github-tools Bot added p: Software Mansion Partner: Software Mansion Partner labels Oct 28, 2026

This branch has not been deployed

No deployments
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: Software Mansion Partner: Software Mansion Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scrolling a 'moving' FlatList causes it to stutter or block scrolling completely on Android

1 participant