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:
parent
17fcc9440f
commit
4937a4c5cd
|
@ -98,6 +98,20 @@ var styles = StyleSheet.create({
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
backgroundColor: 'lightgrey',
|
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';
|
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]} />;
|
||||||
|
}
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -77,6 +77,11 @@ public class ViewProps {
|
||||||
public static final String BORDER_TOP_WIDTH = "borderTopWidth";
|
public static final String BORDER_TOP_WIDTH = "borderTopWidth";
|
||||||
public static final String BORDER_RIGHT_WIDTH = "borderRightWidth";
|
public static final String BORDER_RIGHT_WIDTH = "borderRightWidth";
|
||||||
public static final String BORDER_BOTTOM_WIDTH = "borderBottomWidth";
|
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 = {
|
public static final int[] BORDER_SPACING_TYPES = {
|
||||||
Spacing.ALL, Spacing.LEFT, Spacing.RIGHT, Spacing.TOP, Spacing.BOTTOM
|
Spacing.ALL, Spacing.LEFT, Spacing.RIGHT, Spacing.TOP, Spacing.BOTTOM
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@ package com.facebook.react.views.view;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
@ -78,7 +79,9 @@ import com.facebook.csslayout.Spacing;
|
||||||
/* Used for rounded border and rounded background */
|
/* Used for rounded border and rounded background */
|
||||||
private @Nullable PathEffect mPathEffectForBorderStyle;
|
private @Nullable PathEffect mPathEffectForBorderStyle;
|
||||||
private @Nullable Path mPathForBorderRadius;
|
private @Nullable Path mPathForBorderRadius;
|
||||||
|
private @Nullable Path mPathForBorderRadiusOutline;
|
||||||
private @Nullable RectF mTempRectForBorderRadius;
|
private @Nullable RectF mTempRectForBorderRadius;
|
||||||
|
private @Nullable RectF mTempRectForBorderRadiusOutline;
|
||||||
private boolean mNeedUpdatePathForBorderRadius = false;
|
private boolean mNeedUpdatePathForBorderRadius = false;
|
||||||
private float mBorderRadius = CSSConstants.UNDEFINED;
|
private float mBorderRadius = CSSConstants.UNDEFINED;
|
||||||
|
|
||||||
|
@ -87,9 +90,11 @@ import com.facebook.csslayout.Spacing;
|
||||||
private int mColor = Color.TRANSPARENT;
|
private int mColor = Color.TRANSPARENT;
|
||||||
private int mAlpha = 255;
|
private int mAlpha = 255;
|
||||||
|
|
||||||
|
private @Nullable float[] mBorderCornerRadii;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Canvas canvas) {
|
public void draw(Canvas canvas) {
|
||||||
if (!CSSConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) {
|
if ((!CSSConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) || mBorderCornerRadii != null) {
|
||||||
drawRoundedBackgroundWithBorders(canvas);
|
drawRoundedBackgroundWithBorders(canvas);
|
||||||
} else {
|
} else {
|
||||||
drawRectangularBackgroundWithBorders(canvas);
|
drawRectangularBackgroundWithBorders(canvas);
|
||||||
|
@ -132,11 +137,10 @@ import com.facebook.csslayout.Spacing;
|
||||||
super.getOutline(outline);
|
super.getOutline(outline);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!CSSConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) {
|
if((!CSSConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) || mBorderCornerRadii != null) {
|
||||||
float extraRadiusFromBorderWidth = (mBorderWidth != null)
|
updatePath();
|
||||||
? mBorderWidth.get(Spacing.ALL) / 2f
|
|
||||||
: 0;
|
outline.setConvexPath(mPathForBorderRadiusOutline);
|
||||||
outline.setRoundRect(getBounds(), mBorderRadius + extraRadiusFromBorderWidth);
|
|
||||||
} else {
|
} else {
|
||||||
outline.setRect(getBounds());
|
outline.setRect(getBounds());
|
||||||
}
|
}
|
||||||
|
@ -181,8 +185,22 @@ import com.facebook.csslayout.Spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRadius(float radius) {
|
public void setRadius(float radius) {
|
||||||
if (mBorderRadius != radius) {
|
if (!FloatUtil.floatsEqual(mBorderRadius,radius)) {
|
||||||
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();
|
invalidateSelf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,19 +243,61 @@ import com.facebook.csslayout.Spacing;
|
||||||
if (mPathForBorderRadius == null) {
|
if (mPathForBorderRadius == null) {
|
||||||
mPathForBorderRadius = new Path();
|
mPathForBorderRadius = new Path();
|
||||||
mTempRectForBorderRadius = new RectF();
|
mTempRectForBorderRadius = new RectF();
|
||||||
|
mPathForBorderRadiusOutline = new Path();
|
||||||
|
mTempRectForBorderRadiusOutline = new RectF();
|
||||||
}
|
}
|
||||||
|
|
||||||
mPathForBorderRadius.reset();
|
mPathForBorderRadius.reset();
|
||||||
|
mPathForBorderRadiusOutline.reset();
|
||||||
|
|
||||||
mTempRectForBorderRadius.set(getBounds());
|
mTempRectForBorderRadius.set(getBounds());
|
||||||
|
mTempRectForBorderRadiusOutline.set(getBounds());
|
||||||
float fullBorderWidth = getFullBorderWidth();
|
float fullBorderWidth = getFullBorderWidth();
|
||||||
if (fullBorderWidth > 0) {
|
if (fullBorderWidth > 0) {
|
||||||
mTempRectForBorderRadius.inset(fullBorderWidth * 0.5f, fullBorderWidth * 0.5f);
|
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(
|
mPathForBorderRadius.addRoundRect(
|
||||||
mTempRectForBorderRadius,
|
mTempRectForBorderRadius,
|
||||||
mBorderRadius,
|
new float[] {
|
||||||
mBorderRadius,
|
topLeftRadius,
|
||||||
|
topLeftRadius,
|
||||||
|
topRightRadius,
|
||||||
|
topRightRadius,
|
||||||
|
bottomRightRadius,
|
||||||
|
bottomRightRadius,
|
||||||
|
bottomLeftRadius,
|
||||||
|
bottomLeftRadius
|
||||||
|
},
|
||||||
Path.Direction.CW);
|
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
|
mPathEffectForBorderStyle = mBorderStyle != null
|
||||||
? mBorderStyle.getPathEffect(getFullBorderWidth())
|
? mBorderStyle.getPathEffect(getFullBorderWidth())
|
||||||
: null;
|
: null;
|
||||||
|
|
|
@ -207,6 +207,10 @@ public class ReactViewGroup extends ViewGroup implements
|
||||||
getOrCreateReactViewBackground().setRadius(borderRadius);
|
getOrCreateReactViewBackground().setRadius(borderRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBorderRadius(float borderRadius, int position) {
|
||||||
|
getOrCreateReactViewBackground().setRadius(borderRadius, position);
|
||||||
|
}
|
||||||
|
|
||||||
public void setBorderStyle(@Nullable String style) {
|
public void setBorderStyle(@Nullable String style) {
|
||||||
getOrCreateReactViewBackground().setBorderStyle(style);
|
getOrCreateReactViewBackground().setBorderStyle(style);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,23 @@ public class ReactViewManager extends ViewGroupManager<ReactViewGroup> {
|
||||||
view.setFocusable(accessible);
|
view.setFocusable(accessible);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "borderRadius")
|
@ReactPropGroup(names = {
|
||||||
public void setBorderRadius(ReactViewGroup view, float borderRadius) {
|
ViewProps.BORDER_RADIUS,
|
||||||
view.setBorderRadius(PixelUtil.toPixelFromDIP(borderRadius));
|
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")
|
@ReactProp(name = "borderStyle")
|
||||||
|
|
Loading…
Reference in New Issue