Added support for corner radii in Android

Summary:
This is a cut down version of a previous pull request with just the 4 corners catered for.
Closes https://github.com/facebook/react-native/pull/4252

Reviewed By: svcscm

Differential Revision: D2911959

Pulled By: androidtrunkagent

fb-gh-sync-id: 7ddcd684d90d4d92ccefed906c0126e92818dcde
This commit is contained in:
mattds 2016-02-08 10:42:31 -08:00 committed by facebook-github-bot-7
parent 17fcc9440f
commit 4937a4c5cd
5 changed files with 124 additions and 12 deletions

View File

@ -98,6 +98,20 @@ var styles = StyleSheet.create({
marginRight: 10,
backgroundColor: 'lightgrey',
},
border9: {
borderWidth: 10,
borderTopLeftRadius: 10,
borderBottomRightRadius: 20,
borderColor: 'black',
},
border10: {
borderWidth: 10,
backgroundColor: 'white',
borderTopLeftRadius: 10,
borderBottomRightRadius: 20,
borderColor: 'black',
elevation: 10
}
});
exports.title = 'Border';
@ -180,4 +194,19 @@ exports.examples = [
);
}
},
{
title: 'Corner Radii',
description: 'borderTopLeftRadius & borderBottomRightRadius',
render() {
return <View style={[styles.box, styles.border9]} />;
}
},
{
title: 'Corner Radii / Elevation',
description: 'borderTopLeftRadius & borderBottomRightRadius & elevation',
platform: 'android',
render() {
return <View style={[styles.box, styles.border10]} />;
}
},
];

View File

@ -77,6 +77,11 @@ public class ViewProps {
public static final String BORDER_TOP_WIDTH = "borderTopWidth";
public static final String BORDER_RIGHT_WIDTH = "borderRightWidth";
public static final String BORDER_BOTTOM_WIDTH = "borderBottomWidth";
public static final String BORDER_RADIUS = "borderRadius";
public static final String BORDER_TOP_LEFT_RADIUS = "borderTopLeftRadius";
public static final String BORDER_TOP_RIGHT_RADIUS = "borderTopRightRadius";
public static final String BORDER_BOTTOM_LEFT_RADIUS = "borderBottomLeftRadius";
public static final String BORDER_BOTTOM_RIGHT_RADIUS = "borderBottomRightRadius";
public static final int[] BORDER_SPACING_TYPES = {
Spacing.ALL, Spacing.LEFT, Spacing.RIGHT, Spacing.TOP, Spacing.BOTTOM
};

View File

@ -11,6 +11,7 @@ package com.facebook.react.views.view;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Locale;
import android.graphics.Canvas;
@ -78,7 +79,9 @@ import com.facebook.csslayout.Spacing;
/* Used for rounded border and rounded background */
private @Nullable PathEffect mPathEffectForBorderStyle;
private @Nullable Path mPathForBorderRadius;
private @Nullable Path mPathForBorderRadiusOutline;
private @Nullable RectF mTempRectForBorderRadius;
private @Nullable RectF mTempRectForBorderRadiusOutline;
private boolean mNeedUpdatePathForBorderRadius = false;
private float mBorderRadius = CSSConstants.UNDEFINED;
@ -87,9 +90,11 @@ import com.facebook.csslayout.Spacing;
private int mColor = Color.TRANSPARENT;
private int mAlpha = 255;
private @Nullable float[] mBorderCornerRadii;
@Override
public void draw(Canvas canvas) {
if (!CSSConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) {
if ((!CSSConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) || mBorderCornerRadii != null) {
drawRoundedBackgroundWithBorders(canvas);
} else {
drawRectangularBackgroundWithBorders(canvas);
@ -132,11 +137,10 @@ import com.facebook.csslayout.Spacing;
super.getOutline(outline);
return;
}
if(!CSSConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) {
float extraRadiusFromBorderWidth = (mBorderWidth != null)
? mBorderWidth.get(Spacing.ALL) / 2f
: 0;
outline.setRoundRect(getBounds(), mBorderRadius + extraRadiusFromBorderWidth);
if((!CSSConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) || mBorderCornerRadii != null) {
updatePath();
outline.setConvexPath(mPathForBorderRadiusOutline);
} else {
outline.setRect(getBounds());
}
@ -181,8 +185,22 @@ import com.facebook.csslayout.Spacing;
}
public void setRadius(float radius) {
if (mBorderRadius != radius) {
if (!FloatUtil.floatsEqual(mBorderRadius,radius)) {
mBorderRadius = radius;
mNeedUpdatePathForBorderRadius = true;
invalidateSelf();
}
}
public void setRadius(float radius, int position) {
if (mBorderCornerRadii == null) {
mBorderCornerRadii = new float[4];
Arrays.fill(mBorderCornerRadii, CSSConstants.UNDEFINED);
}
if (!FloatUtil.floatsEqual(mBorderCornerRadii[position], radius)) {
mBorderCornerRadii[position] = radius;
mNeedUpdatePathForBorderRadius = true;
invalidateSelf();
}
}
@ -225,19 +243,61 @@ import com.facebook.csslayout.Spacing;
if (mPathForBorderRadius == null) {
mPathForBorderRadius = new Path();
mTempRectForBorderRadius = new RectF();
mPathForBorderRadiusOutline = new Path();
mTempRectForBorderRadiusOutline = new RectF();
}
mPathForBorderRadius.reset();
mPathForBorderRadiusOutline.reset();
mTempRectForBorderRadius.set(getBounds());
mTempRectForBorderRadiusOutline.set(getBounds());
float fullBorderWidth = getFullBorderWidth();
if (fullBorderWidth > 0) {
mTempRectForBorderRadius.inset(fullBorderWidth * 0.5f, fullBorderWidth * 0.5f);
}
float defaultBorderRadius = !CSSConstants.isUndefined(mBorderRadius) ? mBorderRadius : 0;
float topLeftRadius = mBorderCornerRadii != null && !CSSConstants.isUndefined(mBorderCornerRadii[0]) ? mBorderCornerRadii[0] : defaultBorderRadius;
float topRightRadius = mBorderCornerRadii != null && !CSSConstants.isUndefined(mBorderCornerRadii[1]) ? mBorderCornerRadii[1] : defaultBorderRadius;
float bottomRightRadius = mBorderCornerRadii != null && !CSSConstants.isUndefined(mBorderCornerRadii[2]) ? mBorderCornerRadii[2] : defaultBorderRadius;
float bottomLeftRadius = mBorderCornerRadii != null && !CSSConstants.isUndefined(mBorderCornerRadii[3]) ? mBorderCornerRadii[3] : defaultBorderRadius;
mPathForBorderRadius.addRoundRect(
mTempRectForBorderRadius,
mBorderRadius,
mBorderRadius,
new float[] {
topLeftRadius,
topLeftRadius,
topRightRadius,
topRightRadius,
bottomRightRadius,
bottomRightRadius,
bottomLeftRadius,
bottomLeftRadius
},
Path.Direction.CW);
float extraRadiusForOutline = 0;
if (mBorderWidth != null) {
extraRadiusForOutline = mBorderWidth.get(Spacing.ALL) / 2f;
}
mPathForBorderRadiusOutline.addRoundRect(
mTempRectForBorderRadiusOutline,
new float[] {
topLeftRadius + extraRadiusForOutline,
topLeftRadius + extraRadiusForOutline,
topRightRadius + extraRadiusForOutline,
topRightRadius + extraRadiusForOutline,
bottomRightRadius + extraRadiusForOutline,
bottomRightRadius + extraRadiusForOutline,
bottomLeftRadius + extraRadiusForOutline,
bottomLeftRadius + extraRadiusForOutline
},
Path.Direction.CW);
mPathEffectForBorderStyle = mBorderStyle != null
? mBorderStyle.getPathEffect(getFullBorderWidth())
: null;

View File

@ -207,6 +207,10 @@ public class ReactViewGroup extends ViewGroup implements
getOrCreateReactViewBackground().setRadius(borderRadius);
}
public void setBorderRadius(float borderRadius, int position) {
getOrCreateReactViewBackground().setRadius(borderRadius, position);
}
public void setBorderStyle(@Nullable String style) {
getOrCreateReactViewBackground().setBorderStyle(style);
}

View File

@ -51,9 +51,23 @@ public class ReactViewManager extends ViewGroupManager<ReactViewGroup> {
view.setFocusable(accessible);
}
@ReactProp(name = "borderRadius")
public void setBorderRadius(ReactViewGroup view, float borderRadius) {
view.setBorderRadius(PixelUtil.toPixelFromDIP(borderRadius));
@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 = CSSConstants.UNDEFINED)
public void setBorderRadius(ReactViewGroup view, int index, float borderRadius) {
if (!CSSConstants.isUndefined(borderRadius)) {
borderRadius = PixelUtil.toPixelFromDIP(borderRadius);
}
if (index == 0) {
view.setBorderRadius(borderRadius);
} else {
view.setBorderRadius(borderRadius, index - 1);
}
}
@ReactProp(name = "borderStyle")