From 4af4da9089e20aa84bc5660bfb37763556442a4e Mon Sep 17 00:00:00 2001 From: Oleg Lokhvitsky Date: Mon, 24 Sep 2018 10:06:02 -0700 Subject: [PATCH] Android ScrollView support for `overflow: visible` Summary: ScrollView always clipping children on Android even when `overflow: visible` was specified. This change just omits the clipping during draw if `overflow: visible` is passed in. The default is not changed (from hidden to visible) in case there is a performance impact. Android now matches iOS in behavior. This helps with issue #21116 and resolves #14416. Reviewed By: shergin Differential Revision: D9952096 fbshipit-source-id: 367afe33ee7ff0fdc5aa1074d239883aa289888a --- .../scroll/ReactHorizontalScrollView.java | 19 +++++++++++++++++-- .../ReactHorizontalScrollViewManager.java | 5 +++++ .../react/views/scroll/ReactScrollView.java | 19 +++++++++++++++++-- .../views/scroll/ReactScrollViewManager.java | 5 +++++ 4 files changed, 44 insertions(+), 4 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 1a928743b..d92d0784d 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 @@ -27,10 +27,11 @@ import android.widget.OverScroller; import com.facebook.infer.annotation.Assertions; import com.facebook.react.common.ReactConstants; +import com.facebook.react.uimanager.events.NativeGestureUtil; import com.facebook.react.uimanager.MeasureSpecAssertions; import com.facebook.react.uimanager.ReactClippingViewGroup; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; -import com.facebook.react.uimanager.events.NativeGestureUtil; +import com.facebook.react.uimanager.ViewProps; import com.facebook.react.views.view.ReactViewBackgroundManager; import java.lang.reflect.Field; @@ -55,6 +56,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView implements private boolean mActivelyScrolling; private @Nullable Rect mClippingRect; + private @Nullable String mOverflow = ViewProps.HIDDEN; private boolean mDragging; private boolean mPagingEnabled = false; private @Nullable Runnable mPostTouchRunnable; @@ -181,10 +183,23 @@ public class ReactHorizontalScrollView extends HorizontalScrollView implements awakenScrollBars(); } + public void setOverflow(String overflow) { + mOverflow = overflow; + invalidate(); + } + @Override protected void onDraw(Canvas canvas) { getDrawingRect(mRect); - canvas.clipRect(mRect); + + switch (mOverflow) { + case ViewProps.VISIBLE: + break; + case ViewProps.HIDDEN: + canvas.clipRect(mRect); + break; + } + super.onDraw(canvas); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java index 644857b6a..b3980da12 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java @@ -250,4 +250,9 @@ public class ReactHorizontalScrollViewManager float alphaComponent = color == null ? YogaConstants.UNDEFINED : (float) ((int)color >>> 24); view.setBorderColor(SPACING_TYPES[index], rgbComponent, alphaComponent); } + + @ReactProp(name = "overflow") + public void setOverflow(ReactHorizontalScrollView view, @Nullable String overflow) { + view.setOverflow(overflow); + } } 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 db7844788..88db98ad2 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 @@ -24,10 +24,11 @@ import android.widget.ScrollView; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; import com.facebook.react.common.ReactConstants; +import com.facebook.react.uimanager.events.NativeGestureUtil; import com.facebook.react.uimanager.MeasureSpecAssertions; import com.facebook.react.uimanager.ReactClippingViewGroup; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; -import com.facebook.react.uimanager.events.NativeGestureUtil; +import com.facebook.react.uimanager.ViewProps; import com.facebook.react.views.view.ReactViewBackgroundManager; import java.lang.reflect.Field; @@ -54,6 +55,7 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou private boolean mActivelyScrolling; private @Nullable Rect mClippingRect; + private @Nullable String mOverflow = ViewProps.HIDDEN; private boolean mDragging; private boolean mPagingEnabled = false; private @Nullable Runnable mPostTouchRunnable; @@ -169,6 +171,11 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou awakenScrollBars(); } + public void setOverflow(String overflow) { + mOverflow = overflow; + invalidate(); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { MeasureSpecAssertions.assertExplicitMeasureSpec(widthMeasureSpec, heightMeasureSpec); @@ -373,7 +380,15 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou } } getDrawingRect(mRect); - canvas.clipRect(mRect); + + switch (mOverflow) { + case ViewProps.VISIBLE: + break; + case ViewProps.HIDDEN: + canvas.clipRect(mRect); + break; + } + super.draw(canvas); } 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 6f422fa9b..a2b35975c 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 @@ -245,6 +245,11 @@ public class ReactScrollViewManager view.setBorderColor(SPACING_TYPES[index], rgbComponent, alphaComponent); } + @ReactProp(name = "overflow") + public void setOverflow(ReactScrollView view, @Nullable String overflow) { + view.setOverflow(overflow); + } + @Override public void scrollToEnd( ReactScrollView scrollView,