Skip to content

Commit 2f86aaf

Browse files
Almourofacebook-github-bot
authored andcommitted
Fix scrollview momentum not stopping on scrollTo/scrollToEnd for horizontal scrollviews (#39529)
Summary: ### Motivation My main motivation for this is using nested horizontal `Flashlists` inside a vertical `Flashlist`. Like a `RecyclerView`, since my horizontal lists get recycled, if I scroll say the first horizontal list and scroll down, then when this list gets recycled it continues scrolling even if the content is new: ![nested-list-recycling](https://github.com/facebook/react-native/assets/4534323/f75a2a9b-6ab5-4554-811f-8d85ddfb81de) To handle this, I want to call `scrollTo` everytime a new row appears to reset the scroll offset, however I've realized this doesn't stop the scroll momentum ### The bug When scrolling and calling `scrollTo`, scroll momentum should be stopped and we should scroll to where `scrollTo` asked for. All credit goes to tomekzaw for #36104 who fixed it for vertical scrollviews I realized we had the same issue for - horizontal scroll views - when calling `scrollToEnd` | Vertical scrollview (working ✅) | Horizontal scrollview (before fix, not stopping ❌) | Horizontal scrollview (after fix ✅)| |--------|--------|--| | ![vertical-scrolltoffset-working](https://github.com/facebook/react-native/assets/4534323/884d95ce-9b09-47aa-99a7-99ca579a8fc4)|![horizontal-scrolloffset-bug](https://github.com/facebook/react-native/assets/4534323/0065a9d0-f905-4354-9caa-29a0a1f914ba)|![horizontal-scrolloffset-fixed](https://github.com/facebook/react-native/assets/4534323/ab49c356-23e8-464a-83a9-c4632b9d673e)| Based on #38728 I kept all those calls to `abortAnimation` on the View Manager ## Changelog: [ANDROID] [FIXED] - Fixed horizontal ScrollView momentum not stopping when calling scrollTo programmatically [ANDROID] [FIXED] - Fixed ScrollView momentum not stopping when calling scrollToEnd programmatically Pull Request resolved: #39529 Test Plan: My test code is [this](https://gist.github.com/Almouro/3ffcfbda8e2239e64bee93985e243000) Basically: - a scrollview with a few elements - some buttons to trigger a `scrollTo` To reproduce the bug, I scroll then click one of the buttons triggering a `scrollTo` I added `react-native@nightly` to my project, and copy pasted `packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll` folder from this branch to try out my fixes Then tested the following scenarios on Android: | List layout | Method | Not animated | Animated| |--------|--------|--|--| | horizontal | scrollTo | ![horizontal-scrollTo-no](https://github.com/facebook/react-native/assets/4534323/bda87a19-43cf-4fe9-9340-f70a3d5cd6a4)| ![horizontal-scrollto-yes](https://github.com/facebook/react-native/assets/4534323/8628d7ff-ee28-4185-81d1-1783f0fd990f) | | horizontal | scrollToEnd |![horizontal-scrolltoend-no](https://github.com/facebook/react-native/assets/4534323/594bb539-cb27-4234-8a8f-74d5b2bbe25f) | ![horizontal-scrolltoend-yes](https://github.com/facebook/react-native/assets/4534323/7366abcd-95fb-42ab-89e1-38fd4b10d966)| | vertical | scrollTo | ![vertical-scrollto-no](https://github.com/facebook/react-native/assets/4534323/54555250-d4df-4bc2-b20f-46c706e8c726)|![vertical-scrollto-yes](https://github.com/facebook/react-native/assets/4534323/0c109f81-0bbd-475b-90f1-f1467317c799) | | vertical | scrollToEnd | ![vertical-scrolltoend-no](https://github.com/facebook/react-native/assets/4534323/f48c8196-8f2f-4d98-b750-91c067d1a063) | ![vertical-scrolltoend-yes](https://github.com/facebook/react-native/assets/4534323/04bb06dc-7e20-40de-a40d-e1da1fec491a)| Reviewed By: javache Differential Revision: D49437886 Pulled By: ryancat fbshipit-source-id: 358c9b0eed7dabcbc9b87a15d1a757b414ef514b
1 parent 196b3f9 commit 2f86aaf

File tree

3 files changed

+9
-0
lines changed

3 files changed

+9
-0
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,12 @@ public void setDecelerationRate(float decelerationRate) {
231231
}
232232
}
233233

234+
public void abortAnimation() {
235+
if (mScroller != null && !mScroller.isFinished()) {
236+
mScroller.abortAnimation();
237+
}
238+
}
239+
234240
public void setSnapInterval(int snapInterval) {
235241
mSnapInterval = snapInterval;
236242
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ public void flashScrollIndicators(ReactHorizontalScrollView scrollView) {
199199
@Override
200200
public void scrollTo(
201201
ReactHorizontalScrollView scrollView, ReactScrollViewCommandHelper.ScrollToCommandData data) {
202+
scrollView.abortAnimation();
202203
if (data.mAnimated) {
203204
scrollView.reactSmoothScrollTo(data.mDestX, data.mDestY);
204205
} else {
@@ -219,6 +220,7 @@ public void scrollToEnd(
219220
"scrollToEnd called on HorizontalScrollView without child");
220221
}
221222
int right = child.getWidth() + scrollView.getPaddingRight();
223+
scrollView.abortAnimation();
222224
if (data.mAnimated) {
223225
scrollView.reactSmoothScrollTo(right, scrollView.getScrollY());
224226
} else {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ public void scrollToEnd(
296296

297297
// ScrollView always has one child - the scrollable area
298298
int bottom = child.getHeight() + scrollView.getPaddingBottom();
299+
scrollView.abortAnimation();
299300
if (data.mAnimated) {
300301
scrollView.reactSmoothScrollTo(scrollView.getScrollX(), bottom);
301302
} else {

0 commit comments

Comments
 (0)