From 9f6f97151c44a0f727c9dd938222be1860ecf3f9 Mon Sep 17 00:00:00 2001 From: Genki Kondo Date: Tue, 15 Feb 2022 13:03:46 -0800 Subject: [PATCH] Fix ReactHorizontalScrollView contentOffset Summary: Brings the same fix https://www.internalfb.com/diff/D34015853 (https://github.com/facebook/react-native/commit/be260b9f479a3b55ee43d2959d2c49fd3c1eb4ac) for ReactScrollView to ReactHorizontalScrollView When setting ScrollView's contentOffset, if the ScrollView hasn't been laid out yet when ReactHorizontalScrollViewManager.setContentOffset is called, then scroll position is never set properly. This is because the actual scroll offset (0, 0) was being passed into setPendingContentOffsets, instead of the desired scroll offset. Thus, when ReactHorizontalScrollView.onLayout gets called, ReactHorizontalScrollView.scrollTo gets called with (0, 0). Changelog: [Android][Fixed] - Fix ReactHorizontalScrollView contentOffset Reviewed By: bvanderhoof Differential Revision: D34246489 fbshipit-source-id: d923f7c9f136f7275d64bd658ffd5c2cc049d392 --- .../scroll/ReactHorizontalScrollView.java | 20 +++++++++---------- .../react/views/scroll/ReactScrollView.java | 11 ++++++---- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 27eb3933531..879acf55a78 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -661,8 +661,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView } private View getContentView() { - View contentView = getChildAt(0); - return contentView; + return getChildAt(0); } public void setEndFillColor(int color) { @@ -1191,12 +1190,13 @@ public class ReactHorizontalScrollView extends HorizontalScrollView } super.scrollTo(x, y); - // The final scroll position might be different from (x, y). For example, we may need to scroll - // to the last item in the list, but that item cannot be move to the start position of the view. - final int actualX = getScrollX(); - final int actualY = getScrollY(); - ReactScrollViewHelper.updateFabricScrollState(this, actualX, actualY); - setPendingContentOffsets(actualX, actualY); + ReactScrollViewHelper.updateFabricScrollState(this); + setPendingContentOffsets(x, y); + } + + private boolean isContentReady() { + View child = getContentView(); + return child != null && child.getWidth() != 0 && child.getHeight() != 0; } /** @@ -1210,8 +1210,8 @@ public class ReactHorizontalScrollView extends HorizontalScrollView if (DEBUG_MODE) { FLog.i(TAG, "setPendingContentOffsets[%d] x %d y %d", getId(), x, y); } - View child = getContentView(); - if (child != null && child.getWidth() != 0 && child.getHeight() != 0) { + + if (isContentReady()) { pendingContentOffsetX = UNSET_CONTENT_OFFSET; pendingContentOffsetY = UNSET_CONTENT_OFFSET; } else { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 8624f648dd0..4c832ab6f09 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -954,10 +954,13 @@ public class ReactScrollView extends ScrollView } /** - * Calls `updateFabricScrollState` and updates state. + * Calls `super.scrollTo` and updates state. * - *

`scrollTo` changes `contentOffset` and we need to keep `contentOffset` in sync between - * scroll view and state. Calling ScrollView's `scrollTo` doesn't update state. + *

`super.scrollTo` changes `contentOffset` and we need to keep `contentOffset` in sync between + * scroll view and state. + * + *

Note that while we can override scrollTo, we *cannot* override `smoothScrollTo` because it + * is final. See `reactSmoothScrollTo`. */ @Override public void scrollTo(int x, int y) { @@ -967,7 +970,7 @@ public class ReactScrollView extends ScrollView } private boolean isContentReady() { - View child = getChildAt(0); + View child = getContentView(); return child != null && child.getWidth() != 0 && child.getHeight() != 0; }