From 4498bc819730e3c513750a04d705883f1d61816d Mon Sep 17 00:00:00 2001 From: Nathan Spaun Date: Wed, 30 Mar 2016 18:05:06 -0700 Subject: [PATCH] Add prop to FbReactScrollView to fill the rest of the background to avoid overdraw Reviewed By: foghina Differential Revision: D3079290 fb-gh-sync-id: b824d235ca34f8e0408f5f40e6b73e028006ac9f fbshipit-source-id: b824d235ca34f8e0408f5f40e6b73e028006ac9f --- Libraries/Components/ScrollView/ScrollView.js | 10 ++++++++ .../scroll/ReactHorizontalScrollView.java | 25 +++++++++++++++++++ .../ReactHorizontalScrollViewManager.java | 13 ++++++++++ .../react/views/scroll/ReactScrollView.java | 25 +++++++++++++++++++ .../views/scroll/ReactScrollViewManager.java | 13 ++++++++++ 5 files changed, 86 insertions(+) diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index ce168b1c2..7d513b15e 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -11,6 +11,7 @@ */ 'use strict'; +var ColorPropType = require('ColorPropType'); var EdgeInsetsPropType = require('EdgeInsetsPropType'); var Platform = require('Platform'); var PointPropType = require('PointPropType'); @@ -318,6 +319,15 @@ var ScrollView = React.createClass({ PropTypes.func, 'Use the `refreshControl` prop instead.' ), + + /** + * Sometimes a scrollview takes up more space than its content fills. When this is + * the case, this prop will fill the rest of the scrollview with a color to avoid setting + * a background and creating unnecessary overdraw. This is an advanced optimization + * that is not needed in the general case. + * @platform android + */ + endFillColor: ColorPropType, }, mixins: [ScrollResponder.Mixin], 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 e35dd0647..2b294fcde 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 @@ -12,7 +12,11 @@ package com.facebook.react.views.scroll; import javax.annotation.Nullable; import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.view.MotionEvent; import android.view.View; import android.widget.HorizontalScrollView; @@ -38,6 +42,8 @@ public class ReactHorizontalScrollView extends HorizontalScrollView implements private boolean mRemoveClippedSubviews; private boolean mScrollEnabled = true; private boolean mSendMomentumEvents; + private @Nullable Drawable mEndBackground; + private int mEndFillColor = Color.TRANSPARENT; public ReactHorizontalScrollView(Context context) { super(context); @@ -185,4 +191,23 @@ public class ReactHorizontalScrollView extends HorizontalScrollView implements public void getClippingRect(Rect outClippingRect) { outClippingRect.set(Assertions.assertNotNull(mClippingRect)); } + + public void setEndFillColor(int color) { + if (color != mEndFillColor) { + mEndFillColor = color; + mEndBackground = new ColorDrawable(mEndFillColor); + } + } + + @Override + public void draw(Canvas canvas) { + if (mEndFillColor != Color.TRANSPARENT) { + final View content = getChildAt(0); + if (mEndBackground != null && content != null && content.getRight() < getWidth()) { + mEndBackground.setBounds(content.getRight(), 0, getWidth(), getHeight()); + mEndBackground.draw(canvas); + } + } + super.draw(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 69185fef8..1bdd5bc7a 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 @@ -11,6 +11,8 @@ package com.facebook.react.views.scroll; import javax.annotation.Nullable; +import android.graphics.Color; + import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.ThemedReactContext; @@ -85,4 +87,15 @@ public class ReactHorizontalScrollViewManager scrollView.scrollTo(data.mDestX, data.mDestY); } } + + /** + * When set, fills the rest of the scrollview with a color to avoid setting a background and + * creating unnecessary overdraw. + * @param view + * @param color + */ + @ReactProp(name = "endFillColor", defaultInt = Color.TRANSPARENT, customType = "Color") + public void setBottomFillColor(ReactHorizontalScrollView view, int color) { + view.setEndFillColor(color); + } } 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 5e87db3bf..19014159f 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,7 +12,11 @@ package com.facebook.react.views.scroll; import javax.annotation.Nullable; import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.view.MotionEvent; import android.view.View; import android.widget.ScrollView; @@ -41,6 +45,8 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou private boolean mRemoveClippedSubviews; private boolean mScrollEnabled = true; private boolean mSendMomentumEvents; + private @Nullable Drawable mEndBackground; + private int mEndFillColor = Color.TRANSPARENT; public ReactScrollView(Context context) { super(context); @@ -187,4 +193,23 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou postOnAnimationDelayed(r, ReactScrollViewHelper.MOMENTUM_DELAY); } } + + @Override + public void draw(Canvas canvas) { + if (mEndFillColor != Color.TRANSPARENT) { + final View content = getChildAt(0); + if (mEndBackground != null && content != null && content.getBottom() < getHeight()) { + mEndBackground.setBounds(0, content.getBottom(), getWidth(), getHeight()); + mEndBackground.draw(canvas); + } + } + super.draw(canvas); + } + + public void setEndFillColor(int color) { + if (color != mEndFillColor) { + mEndFillColor = color; + mEndBackground = new ColorDrawable(mEndFillColor); + } + } } 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 be023a76a..aa5de96fb 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 @@ -13,6 +13,8 @@ import javax.annotation.Nullable; import java.util.Map; +import android.graphics.Color; + import com.facebook.react.bridge.ReadableArray; import com.facebook.react.common.MapBuilder; import com.facebook.react.uimanager.annotations.ReactProp; @@ -70,6 +72,17 @@ public class ReactScrollViewManager view.setSendMomentumEvents(sendMomentumEvents); } + /** + * When set, fills the rest of the scrollview with a color to avoid setting a background and + * creating unnecessary overdraw. + * @param view + * @param color + */ + @ReactProp(name = "endFillColor", defaultInt = Color.TRANSPARENT, customType = "Color") + public void setBottomFillColor(ReactScrollView view, int color) { + view.setEndFillColor(color); + } + @Override public @Nullable Map getCommandsMap() { return ReactScrollViewCommandHelper.getCommandsMap();