From 7351da26c24bd91ef8093e887a20e3e13eba5510 Mon Sep 17 00:00:00 2001 From: jayshah123 Date: Tue, 26 May 2020 15:32:30 +0530 Subject: [PATCH] Fix last item removal scroll position --- .../scroll/ReactHorizontalScrollView.java | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) 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 c6db70340f8ff9..aeb15058da9858 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 @@ -22,6 +22,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.widget.HorizontalScrollView; import android.widget.OverScroller; import androidx.annotation.Nullable; @@ -48,7 +49,8 @@ /** Similar to {@link ReactScrollView} but only supports horizontal scrolling. */ public class ReactHorizontalScrollView extends HorizontalScrollView - implements ReactClippingViewGroup { + implements ReactClippingViewGroup, ViewGroup.OnHierarchyChangeListener, + View.OnLayoutChangeListener { private static @Nullable Field sScrollerField; private static boolean sTriedToGetScrollerField = false; @@ -81,6 +83,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView private @Nullable List mSnapOffsets; private boolean mSnapToStart = true; private boolean mSnapToEnd = true; + private View mContentView; private ReactViewBackgroundManager mReactBackgroundManager; private boolean mPagedArrowScrolling = false; private int pendingContentOffsetX = UNSET_CONTENT_OFFSET; @@ -106,6 +109,7 @@ public ReactHorizontalScrollView(Context context, @Nullable FpsListener fpsListe mFpsListener = fpsListener; mScroller = getOverScrollerFromParent(); + setOnHierarchyChangeListener(this); } @Nullable @@ -568,6 +572,51 @@ protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolea super.onOverScrolled(scrollX, scrollY, clampedX, clampedY); } + private int getMaxScrollX() { + int contentWidth = mContentView.getWidth(); + int viewportWidth = getWidth() - getPaddingLeft() - getPaddingRight(); + return Math.max(0, contentWidth - viewportWidth); + } + + @Override + public void onChildViewAdded(View parent, View child) { + mContentView = child; + mContentView.addOnLayoutChangeListener(this); + } + + @Override + public void onChildViewRemoved(View parent, View child) { + mContentView.removeOnLayoutChangeListener(this); + mContentView = null; + } + + /** + * Called when a mContentView's layout has changed. Fixes the scroll position if it's too large + * after the content resizes. Without this, the user would see a blank ScrollView when the scroll + * position is larger than the ScrollView's max scroll position after the content shrinks. + */ + @Override + public void onLayoutChange( + View v, + int left, + int top, + int right, + int bottom, + int oldLeft, + int oldTop, + int oldRight, + int oldBottom) { + if (mContentView == null) { + return; + } + + int currentScrollX = getScrollX(); + int maxScrollX = getMaxScrollX(); + if (currentScrollX > maxScrollX) { + scrollTo(maxScrollX, getScrollY()); + } + } + private void enableFpsListener() { if (isScrollPerfLoggingEnabled()) { Assertions.assertNotNull(mFpsListener);