Add border support to ScrollViews

Reviewed By: AaaChiuuu

Differential Revision: D4498409

fbshipit-source-id: e5baca47b647c4fcb37cdad8fad951f6749c65f8
This commit is contained in:
Andrei Coman
2017-02-06 09:04:24 -08:00
committed by Facebook Github Bot
parent d8694a258f
commit 968aa56ca3
5 changed files with 211 additions and 1 deletions

View File

@@ -4,6 +4,7 @@ android_library(
name = 'scroll',
srcs = glob(['*.java']),
deps = [
YOGA_TARGET,
react_native_dep('third-party/android/support/v4:lib-support-v4'),
react_native_dep('third-party/java/infer-annotations:infer-annotations'),
react_native_dep('third-party/java/jsr-305:jsr-305'),
@@ -19,4 +20,3 @@ android_library(
'PUBLIC',
],
)

View File

@@ -18,6 +18,7 @@ import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.view.MotionEvent;
import android.view.View;
import android.widget.HorizontalScrollView;
@@ -27,6 +28,7 @@ import com.facebook.react.uimanager.MeasureSpecAssertions;
import com.facebook.react.uimanager.events.NativeGestureUtil;
import com.facebook.react.uimanager.ReactClippingViewGroup;
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
import com.facebook.react.views.view.ReactViewBackgroundDrawable;
/**
* Similar to {@link ReactScrollView} but only supports horizontal scrolling.
@@ -48,6 +50,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView implements
private @Nullable String mScrollPerfTag;
private @Nullable Drawable mEndBackground;
private int mEndFillColor = Color.TRANSPARENT;
private @Nullable ReactViewBackgroundDrawable mReactBackgroundDrawable;
public ReactHorizontalScrollView(Context context) {
this(context, null);
@@ -312,4 +315,50 @@ public class ReactHorizontalScrollView extends HorizontalScrollView implements
}
smoothScrollTo(page * width, getScrollY());
}
@Override
public void setBackgroundColor(int color) {
if (color == Color.TRANSPARENT && mReactBackgroundDrawable == null) {
// don't do anything, no need to allocate ReactBackgroundDrawable for transparent background
} else {
getOrCreateReactViewBackground().setColor(color);
}
}
public void setBorderWidth(int position, float width) {
getOrCreateReactViewBackground().setBorderWidth(position, width);
}
public void setBorderColor(int position, float color, float alpha) {
getOrCreateReactViewBackground().setBorderColor(position, color, alpha);
}
public void setBorderRadius(float borderRadius) {
getOrCreateReactViewBackground().setRadius(borderRadius);
}
public void setBorderRadius(float borderRadius, int position) {
getOrCreateReactViewBackground().setRadius(borderRadius, position);
}
public void setBorderStyle(@Nullable String style) {
getOrCreateReactViewBackground().setBorderStyle(style);
}
private ReactViewBackgroundDrawable getOrCreateReactViewBackground() {
if (mReactBackgroundDrawable == null) {
mReactBackgroundDrawable = new ReactViewBackgroundDrawable();
Drawable backgroundDrawable = getBackground();
super.setBackground(null); // required so that drawable callback is cleared before we add the
// drawable back as a part of LayerDrawable
if (backgroundDrawable == null) {
super.setBackground(mReactBackgroundDrawable);
} else {
LayerDrawable layerDrawable =
new LayerDrawable(new Drawable[]{mReactBackgroundDrawable, backgroundDrawable});
super.setBackground(layerDrawable);
}
}
return mReactBackgroundDrawable;
}
}

View File

@@ -16,10 +16,15 @@ import android.view.View;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.Spacing;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
import com.facebook.react.uimanager.annotations.ReactPropGroup;
import com.facebook.yoga.YogaConstants;
/**
* View manager for {@link ReactHorizontalScrollView} components.
@@ -34,6 +39,10 @@ public class ReactHorizontalScrollViewManager
protected static final String REACT_CLASS = "AndroidHorizontalScrollView";
private static final int[] SPACING_TYPES = {
Spacing.ALL, Spacing.LEFT, Spacing.RIGHT, Spacing.TOP, Spacing.BOTTOM,
};
private @Nullable FpsListener mFpsListener = null;
public ReactHorizontalScrollViewManager() {
@@ -150,4 +159,52 @@ public class ReactHorizontalScrollViewManager
public void setBottomFillColor(ReactHorizontalScrollView view, int color) {
view.setEndFillColor(color);
}
@ReactPropGroup(names = {
ViewProps.BORDER_RADIUS,
ViewProps.BORDER_TOP_LEFT_RADIUS,
ViewProps.BORDER_TOP_RIGHT_RADIUS,
ViewProps.BORDER_BOTTOM_RIGHT_RADIUS,
ViewProps.BORDER_BOTTOM_LEFT_RADIUS
}, defaultFloat = YogaConstants.UNDEFINED)
public void setBorderRadius(ReactHorizontalScrollView view, int index, float borderRadius) {
if (!YogaConstants.isUndefined(borderRadius)) {
borderRadius = PixelUtil.toPixelFromDIP(borderRadius);
}
if (index == 0) {
view.setBorderRadius(borderRadius);
} else {
view.setBorderRadius(borderRadius, index - 1);
}
}
@ReactProp(name = "borderStyle")
public void setBorderStyle(ReactHorizontalScrollView view, @Nullable String borderStyle) {
view.setBorderStyle(borderStyle);
}
@ReactPropGroup(names = {
ViewProps.BORDER_WIDTH,
ViewProps.BORDER_LEFT_WIDTH,
ViewProps.BORDER_RIGHT_WIDTH,
ViewProps.BORDER_TOP_WIDTH,
ViewProps.BORDER_BOTTOM_WIDTH,
}, defaultFloat = YogaConstants.UNDEFINED)
public void setBorderWidth(ReactHorizontalScrollView view, int index, float width) {
if (!YogaConstants.isUndefined(width)) {
width = PixelUtil.toPixelFromDIP(width);
}
view.setBorderWidth(SPACING_TYPES[index], width);
}
@ReactPropGroup(names = {
"borderColor", "borderLeftColor", "borderRightColor", "borderTopColor", "borderBottomColor"
}, customType = "Color")
public void setBorderColor(ReactHorizontalScrollView view, int index, Integer color) {
float rgbComponent =
color == null ? YogaConstants.UNDEFINED : (float) ((int)color & 0x00FFFFFF);
float alphaComponent = color == null ? YogaConstants.UNDEFINED : (float) ((int)color >>> 24);
view.setBorderColor(SPACING_TYPES[index], rgbComponent, alphaComponent);
}
}

View File

@@ -18,6 +18,7 @@ import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -32,6 +33,7 @@ import com.facebook.react.uimanager.events.NativeGestureUtil;
import com.facebook.react.uimanager.ReactClippingViewGroup;
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.views.view.ReactViewBackgroundDrawable;
/**
* A simple subclass of ScrollView that doesn't dispatch measure and layout to its children and has
@@ -60,6 +62,7 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou
private @Nullable Drawable mEndBackground;
private int mEndFillColor = Color.TRANSPARENT;
private View mContentView;
private @Nullable ReactViewBackgroundDrawable mReactBackgroundDrawable;
public ReactScrollView(ReactContext context) {
this(context, null);
@@ -380,4 +383,49 @@ public class ReactScrollView extends ScrollView implements ReactClippingViewGrou
scrollTo(getScrollX(), maxScrollY);
}
}
public void setBackgroundColor(int color) {
if (color == Color.TRANSPARENT && mReactBackgroundDrawable == null) {
// don't do anything, no need to allocate ReactBackgroundDrawable for transparent background
} else {
getOrCreateReactViewBackground().setColor(color);
}
}
public void setBorderWidth(int position, float width) {
getOrCreateReactViewBackground().setBorderWidth(position, width);
}
public void setBorderColor(int position, float color, float alpha) {
getOrCreateReactViewBackground().setBorderColor(position, color, alpha);
}
public void setBorderRadius(float borderRadius) {
getOrCreateReactViewBackground().setRadius(borderRadius);
}
public void setBorderRadius(float borderRadius, int position) {
getOrCreateReactViewBackground().setRadius(borderRadius, position);
}
public void setBorderStyle(@Nullable String style) {
getOrCreateReactViewBackground().setBorderStyle(style);
}
private ReactViewBackgroundDrawable getOrCreateReactViewBackground() {
if (mReactBackgroundDrawable == null) {
mReactBackgroundDrawable = new ReactViewBackgroundDrawable();
Drawable backgroundDrawable = getBackground();
super.setBackground(null); // required so that drawable callback is cleared before we add the
// drawable back as a part of LayerDrawable
if (backgroundDrawable == null) {
super.setBackground(mReactBackgroundDrawable);
} else {
LayerDrawable layerDrawable =
new LayerDrawable(new Drawable[]{mReactBackgroundDrawable, backgroundDrawable});
super.setBackground(layerDrawable);
}
}
return mReactBackgroundDrawable;
}
}

View File

@@ -19,10 +19,15 @@ import android.view.View;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.Spacing;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
import com.facebook.react.uimanager.annotations.ReactPropGroup;
import com.facebook.yoga.YogaConstants;
/**
* View manager for {@link ReactScrollView} components.
@@ -37,6 +42,10 @@ public class ReactScrollViewManager
protected static final String REACT_CLASS = "RCTScrollView";
private static final int[] SPACING_TYPES = {
Spacing.ALL, Spacing.LEFT, Spacing.RIGHT, Spacing.TOP, Spacing.BOTTOM,
};
private @Nullable FpsListener mFpsListener = null;
public ReactScrollViewManager() {
@@ -139,6 +148,53 @@ public class ReactScrollViewManager
scrollView.scrollTo(data.mDestX, data.mDestY);
}
}
@ReactPropGroup(names = {
ViewProps.BORDER_RADIUS,
ViewProps.BORDER_TOP_LEFT_RADIUS,
ViewProps.BORDER_TOP_RIGHT_RADIUS,
ViewProps.BORDER_BOTTOM_RIGHT_RADIUS,
ViewProps.BORDER_BOTTOM_LEFT_RADIUS
}, defaultFloat = YogaConstants.UNDEFINED)
public void setBorderRadius(ReactScrollView view, int index, float borderRadius) {
if (!YogaConstants.isUndefined(borderRadius)) {
borderRadius = PixelUtil.toPixelFromDIP(borderRadius);
}
if (index == 0) {
view.setBorderRadius(borderRadius);
} else {
view.setBorderRadius(borderRadius, index - 1);
}
}
@ReactProp(name = "borderStyle")
public void setBorderStyle(ReactScrollView view, @Nullable String borderStyle) {
view.setBorderStyle(borderStyle);
}
@ReactPropGroup(names = {
ViewProps.BORDER_WIDTH,
ViewProps.BORDER_LEFT_WIDTH,
ViewProps.BORDER_RIGHT_WIDTH,
ViewProps.BORDER_TOP_WIDTH,
ViewProps.BORDER_BOTTOM_WIDTH,
}, defaultFloat = YogaConstants.UNDEFINED)
public void setBorderWidth(ReactScrollView view, int index, float width) {
if (!YogaConstants.isUndefined(width)) {
width = PixelUtil.toPixelFromDIP(width);
}
view.setBorderWidth(SPACING_TYPES[index], width);
}
@ReactPropGroup(names = {
"borderColor", "borderLeftColor", "borderRightColor", "borderTopColor", "borderBottomColor"
}, customType = "Color")
public void setBorderColor(ReactScrollView view, int index, Integer color) {
float rgbComponent =
color == null ? YogaConstants.UNDEFINED : (float) ((int)color & 0x00FFFFFF);
float alphaComponent = color == null ? YogaConstants.UNDEFINED : (float) ((int)color >>> 24);
view.setBorderColor(SPACING_TYPES[index], rgbComponent, alphaComponent);
}
@Override
public void scrollToEnd(