From 8a118f287c36dcb5ebbaad69709c454ab9dfff60 Mon Sep 17 00:00:00 2001 From: Jonas Lundberg Date: Wed, 16 Aug 2017 11:02:15 +0200 Subject: [PATCH] Add vertical ScrollView content offset on Android This is the (evil) twin commit to: https://github.com/facebook/react-native/pull/12502 Fixes that contentOffset is not available on Vertical scroll-views. Verification: * Create an Android component with a ScrollView. Add enough items to fill beyond the visible screen. Set the content offset to some value that makes the content scroll. Verify that it snaps to the y-axis as expected. * Remove items so screen is no longer filled, keep content offset parameter. Scroll view still works but does not scroll. * Set only one parameter to content-offset (x || y) - parameters are now ignored since they must be a pair. * Remove contentOffset, scrollView still works as before. --- .../react/views/scroll/ReactScrollView.java | 15 ++++++++++++- .../views/scroll/ReactScrollViewManager.java | 21 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) 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 1336a63125937c..7de7f58f228d28 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 @@ -12,6 +12,7 @@ import javax.annotation.Nullable; import java.lang.reflect.Field; +import java.util.HashMap; import android.graphics.Canvas; import android.graphics.Color; @@ -64,6 +65,7 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou private int mEndFillColor = Color.TRANSPARENT; private View mContentView; private @Nullable ReactViewBackgroundDrawable mReactBackgroundDrawable; + private HashMap mContentOffset = null; public ReactScrollView(ReactContext context) { this(context, null); @@ -130,10 +132,21 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { MeasureSpec.getSize(heightMeasureSpec)); } + public void setContentOffset(HashMap contentOffset) { + mContentOffset = contentOffset; + } + + @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // Call with the present values in order to re-layout if necessary - scrollTo(getScrollX(), getScrollY()); + // If contentOffset is set scroll to its position + if (mContentOffset != null) { + scrollTo(mContentOffset.get("x"), mContentOffset.get("y")); + } else { + // Call with the present values in order to re-layout if necessary + scrollTo(getScrollX(), getScrollY()); + } } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java index f110330b5708f0..50c901716ab673 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java @@ -11,12 +11,14 @@ import javax.annotation.Nullable; +import java.util.HashMap; import java.util.Map; import android.graphics.Color; import android.view.View; import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.MapBuilder; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.PixelUtil; @@ -172,6 +174,25 @@ public void setBorderStyle(ReactScrollView view, @Nullable String borderStyle) { view.setBorderStyle(borderStyle); } + /** + * When set, the scrollview will scroll to the given position on initial layout + * @param view + * @param contentOffset + */ + @ReactProp(name = "contentOffset") + public void setContentOffset(ReactScrollView view, ReadableMap contentOffset) { + if (!contentOffset.hasKey("x") || !contentOffset.hasKey("y")) { + return; + } + + int destX = Math.round(PixelUtil.toPixelFromDIP(contentOffset.getDouble("x"))); + int destY = Math.round(PixelUtil.toPixelFromDIP(contentOffset.getDouble("y"))); + HashMap initialOffset = new HashMap(); + initialOffset.put("x", destX); + initialOffset.put("y", destY); + view.setContentOffset(initialOffset); + } + @ReactPropGroup(names = { ViewProps.BORDER_WIDTH, ViewProps.BORDER_LEFT_WIDTH,