Skip to content

Fix TextInput breaking nested scroll gestures on Android - #58757

Open
jasozh wants to merge 3 commits into
react:mainfrom
jasozh:export-D122404118
Open

jasozh wants to merge 3 commits into
react:mainfrom
jasozh:export-D122404118

Conversation

@jasozh

@jasozh jasozh commented Sep 30, 2026

Copy link
Copy Markdown
Contributor

Summary:
Fixes an Android-only bug where TextInputs can interfere with nested scroll gestures, causing scroll events to be performed on the outer parent instead of the inner ScrollView.

Root Cause

This issue occurs when you have a TextInput inside an inner ScrollView with nestedScrollEnabled = true inside an outer ScrollView. When a scroll gesture is performed on a TextInput that can scroll, the TextInput intercepts the gesture as expected. However, the next scroll gesture applied anywhere in the inner ScrollView scrolls the outer parent instead of the inner ScrollView.

inner.onInterceptTouchEvent() calls startNestedScroll() on ACTION_DOWN and stopNestedScroll() on ACTION_UP. When the scroll gesture is on a scrollable TextInput, ReactEditText disallows parent views from intercepting touch events. This means on ACTION_UP, inner.onInterceptTouchEvent() and stopNestedScroll() is not triggered.

Without stopNestedScroll(), the subsequent startNestedScroll() on the next ACTION_DOWN becomes a no-op, and the outer ScrollView intercepts the scroll gesture instead of the inner ScrollView.

This PR

Add a defensive stopNestedScroll() in dispatchTouchEvent() for ScrollViews. This matches the existing pattern already used by Android in View.dispatchTouchEvent() which includes the exact same defensive cleanup.

Changelog: [Android][Fixed] Prevent TextInputs from interfering with nested scroll gestures

Differential Revision: D122404118

Summary:

Add a new RNTester example in ScrollViewExample for using the component with TextInputs. This reproduces the issue where TextInputs on Android absorb scroll gestures when textAlign is set to "center" or "right". For TextInputs inside a ScrollView, starting a scroll gesture on the TextInput would not scroll the ScrollView. As this is a common use case, the example acts as a reference to show intended behavior and prevent future regressions.

Changelog: [Internal]

Differential Revision: D122199421
Summary:

Fixes the issue described in react#25594 and react#12167, where TextInputs on Android absorb scroll gestures when textAlign is set to "center" or "right". For TextInputs inside a ScrollView, starting a scroll gesture on the TextInput would not scroll the ScrollView.

### Root Cause

The root cause is the `onTouchEvent()` function introduced in [commit 372d001](react@372d001). The smart scroll implementation checks if the TextInput can itself scroll in any direction. If it cannot, then the parent can intercept the gesture to apply normal scroll behavior.

However, when textAlign is set to "center" or "right", `canScrollHorizontally()` returns true, as Android treats the TextInput as capable of scrolling left/right. In these cases, the existing conditional logic blocks all scroll gestures, even if a vertical swipe is applied.

### This PR

Modify `ReactEditText` so that we only check to see if the TextInput can scroll in the direction of the provided touch gesture. If a TextInput can scroll horizontally but not vertically, vertical touch swipes will no longer interfere with the scroll gesture. Touch slop is also used to distinguish intentional swipe gestures from small micro-touch events.

Changelog: [Android][Fixed] Prevent TextInput from preventing scroll gestures

Differential Revision: D121519676
Summary:
Fixes an Android-only bug where TextInputs can interfere with nested scroll gestures, causing scroll events to be performed on the outer parent instead of the inner ScrollView.

### Root Cause

This issue occurs when you have a TextInput inside an inner ScrollView with `nestedScrollEnabled = true` inside an outer ScrollView. When a scroll gesture is performed on a TextInput that can scroll, the TextInput intercepts the gesture as expected. However, the next scroll gesture applied anywhere in the inner ScrollView scrolls the outer parent instead of the inner ScrollView.

`inner.onInterceptTouchEvent()` calls `startNestedScroll()` on ACTION_DOWN and `stopNestedScroll()` on ACTION_UP. When the scroll gesture is on a scrollable TextInput, ReactEditText disallows parent views from intercepting touch events. This means on ACTION_UP, `inner.onInterceptTouchEvent()` and `stopNestedScroll()` is not triggered.

Without `stopNestedScroll()`, the subsequent `startNestedScroll()` on the next ACTION_DOWN becomes a no-op, and the outer ScrollView intercepts the scroll gesture instead of the inner ScrollView.

### This PR

Add a defensive `stopNestedScroll()` in `dispatchTouchEvent()` for ScrollViews. This matches the existing pattern already used by Android in `View.dispatchTouchEvent()` which includes the exact same defensive cleanup.

Changelog: [Android][Fixed] Prevent TextInputs from interfering with nested scroll gestures

Differential Revision: D122404118
@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 Sep 30, 2026
@meta-codesync

meta-codesync Bot commented Sep 30, 2026

Copy link
Copy Markdown

@jasozh has exported this pull request. If you are a Meta employee, you can view the originating Diff in D122404118.

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. meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant