Skip to content

Commit

Permalink
Fix Android ScrollView not responding to Keyboard events when nested …
Browse files Browse the repository at this point in the history
…inside a KeyboardAvoidingView (facebook#38728)

Summary:
Starting from RN 0.72.0, when we nest a ScrollView inside a KeyboardAvoidingView, the ScrollView doesn't respond properly to the Keyboard on Android.

https://github.com/facebook/react-native/assets/32062066/a62b5a42-6817-4093-91a2-7cc9e4a315bb

This issue is due to a change made in facebook#36104, which was added to fix facebook#32235.

That commit changed this line of code to abort the Scroller animation if a new call to the `scrollTo` method was made:

https://github.com/facebook/react-native/blob/aab52859a447a8257b106fe307008af218322e3d/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java#L1073

Apparently, this is the same method that scrolls the ScrollView in response to the Keyboard opening on Android.

So, here comes my proposal for a fix that doesn't break facebook#36104 and fixes facebook#38152.

When we open the Keyboard, the call stack is as follows:
- InputMethodManager
- AndroidIME
- InsetsController
- `ReactScrollView.scrollTo` gets called

When we use the ScrollView method `scrollTo` directly from the UI, the call stack is different as it goes through:
- ReactScrollViewCommandHelper
- ReactScrollViewManager
- `ReactScrollView.scrollTo` gets called

We can move `mScroller.abortAnimation();` from `ReactScrollView.scrollTo` to the `ReactScrollViewManager.scrollTo` method so that it gets called only when we call `scrollTo` from the UI and not when the `scrollTo` method is called by other sources.

https://github.com/facebook/react-native/assets/32062066/9c10ded3-08e5-48e0-9a85-0987d62de011

## Changelog:

[ANDROID] [FIXED] - Fixed ScrollView not responding to Keyboard events when nested inside a KeyboardAvoidingView

Pull Request resolved: facebook#38728

Test Plan: You can see the issue and the proposed fixes in this repo: [kav-test-android](https://github.com/andreacassani/kav-test-android). Please refer to the `kav_test_fix` folder and to the [readme](https://github.com/andreacassani/kav-test-android/blob/main/README.md).

Reviewed By: NickGerleman

Differential Revision: D47972445

Pulled By: ryancat

fbshipit-source-id: e58758d4b3d5318b947b42a88a56ad6ae69a539c
  • Loading branch information
andreacassani authored and Kudo committed Aug 21, 2023
1 parent d707fe9 commit becd669
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ public void setDecelerationRate(float decelerationRate) {
}
}

public void abortAnimation() {
if (mScroller != null && !mScroller.isFinished()) {
mScroller.abortAnimation();
}
}

public void setSnapInterval(int snapInterval) {
mSnapInterval = snapInterval;
}
Expand Down Expand Up @@ -1076,7 +1082,6 @@ public void reactSmoothScrollTo(int x, int y) {
*/
@Override
public void scrollTo(int x, int y) {
mScroller.abortAnimation();
super.scrollTo(x, y);
ReactScrollViewHelper.updateFabricScrollState(this);
setPendingContentOffsets(x, y);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ public void flashScrollIndicators(ReactScrollView scrollView) {
@Override
public void scrollTo(
ReactScrollView scrollView, ReactScrollViewCommandHelper.ScrollToCommandData data) {
scrollView.abortAnimation();
if (data.mAnimated) {
scrollView.reactSmoothScrollTo(data.mDestX, data.mDestY);
} else {
Expand Down

0 comments on commit becd669

Please sign in to comment.