From a0f8fc9a52a62703e8815630a36da158d7853db4 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 f544aafdb66db6..08dd65f1546332 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 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; @@ -171,10 +173,23 @@ public void flashScrollIndicators() { 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 2f65a7c8922579..baf40d9f6880b5 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 @@ -240,4 +240,9 @@ public void setBorderColor(ReactHorizontalScrollView view, int index, Integer co 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 9df87e57e7404f..7388ab8872b4ad 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 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; @@ -159,6 +161,11 @@ public void flashScrollIndicators() { awakenScrollBars(); } + public void setOverflow(String overflow) { + mOverflow = overflow; + invalidate(); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { MeasureSpecAssertions.assertExplicitMeasureSpec(widthMeasureSpec, heightMeasureSpec); @@ -363,7 +370,15 @@ public void draw(Canvas canvas) { } } 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 413b825ec9f5ec..fbca7642b4a736 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 @@ -235,6 +235,11 @@ public void setBorderColor(ReactScrollView view, int index, Integer color) { 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,