iOS: Implement border(Top|Bottom)(Start|End)Radius and border(Start|End)(Color|Width) RN styles
Reviewed By: shergin Differential Revision: D5874536 fbshipit-source-id: 5ad237bddb70745aef0341cddb172da5ee388c38
This commit is contained in:
parent
38b5506599
commit
1b5f8d3ee5
|
@ -40,6 +40,8 @@ ReactNativeStyleAttributes.borderColor = colorAttributes;
|
|||
ReactNativeStyleAttributes.borderLeftColor = colorAttributes;
|
||||
ReactNativeStyleAttributes.borderRightColor = colorAttributes;
|
||||
ReactNativeStyleAttributes.borderTopColor = colorAttributes;
|
||||
ReactNativeStyleAttributes.borderStartColor = colorAttributes;
|
||||
ReactNativeStyleAttributes.borderEndColor = colorAttributes;
|
||||
ReactNativeStyleAttributes.color = colorAttributes;
|
||||
ReactNativeStyleAttributes.shadowColor = colorAttributes;
|
||||
ReactNativeStyleAttributes.textDecorationColor = colorAttributes;
|
||||
|
|
|
@ -31,11 +31,17 @@ var ViewStylePropTypes = {
|
|||
borderRightColor: ColorPropType,
|
||||
borderBottomColor: ColorPropType,
|
||||
borderLeftColor: ColorPropType,
|
||||
borderStartColor: ColorPropType,
|
||||
borderEndColor: ColorPropType,
|
||||
borderRadius: ReactPropTypes.number,
|
||||
borderTopLeftRadius: ReactPropTypes.number,
|
||||
borderTopRightRadius: ReactPropTypes.number,
|
||||
borderTopStartRadius: ReactPropTypes.number,
|
||||
borderTopEndRadius: ReactPropTypes.number,
|
||||
borderBottomLeftRadius: ReactPropTypes.number,
|
||||
borderBottomRightRadius: ReactPropTypes.number,
|
||||
borderBottomStartRadius: ReactPropTypes.number,
|
||||
borderBottomEndRadius: ReactPropTypes.number,
|
||||
borderStyle: ReactPropTypes.oneOf(['solid', 'dotted', 'dashed']),
|
||||
borderWidth: ReactPropTypes.number,
|
||||
borderTopWidth: ReactPropTypes.number,
|
||||
|
|
|
@ -325,6 +325,18 @@ var LayoutPropTypes = {
|
|||
*/
|
||||
borderTopWidth: ReactPropTypes.number,
|
||||
|
||||
/**
|
||||
* When direction is `ltr`, `borderStartWidth` is equivalent to `borderLeftWidth`.
|
||||
* When direction is `rtl`, `borderStartWidth` is equivalent to `borderRightWidth`.
|
||||
*/
|
||||
borderStartWidth: ReactPropTypes.number,
|
||||
|
||||
/**
|
||||
* When direction is `ltr`, `borderEndWidth` is equivalent to `borderRightWidth`.
|
||||
* When direction is `rtl`, `borderEndWidth` is equivalent to `borderLeftWidth`.
|
||||
*/
|
||||
borderEndWidth: ReactPropTypes.number,
|
||||
|
||||
/** `borderRightWidth` works like `border-right-width` in CSS.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width
|
||||
* for more details.
|
||||
|
|
|
@ -122,6 +122,8 @@ typedef void (^RCTApplierBlock)(NSDictionary<NSNumber *, UIView *> *viewRegistry
|
|||
@property (nonatomic, assign) float borderLeftWidth;
|
||||
@property (nonatomic, assign) float borderBottomWidth;
|
||||
@property (nonatomic, assign) float borderRightWidth;
|
||||
@property (nonatomic, assign) float borderStartWidth;
|
||||
@property (nonatomic, assign) float borderEndWidth;
|
||||
|
||||
/**
|
||||
* Margin. Defaults to { 0, 0, 0, 0 }.
|
||||
|
|
|
@ -26,6 +26,8 @@ typedef NS_ENUM(unsigned int, meta_prop_t) {
|
|||
META_PROP_TOP,
|
||||
META_PROP_RIGHT,
|
||||
META_PROP_BOTTOM,
|
||||
META_PROP_START,
|
||||
META_PROP_END,
|
||||
META_PROP_HORIZONTAL,
|
||||
META_PROP_VERTICAL,
|
||||
META_PROP_ALL,
|
||||
|
@ -121,8 +123,17 @@ static void RCTProcessMetaPropsMargin(const YGValue metaProps[META_PROP_COUNT],
|
|||
}
|
||||
|
||||
static void RCTProcessMetaPropsBorder(const YGValue metaProps[META_PROP_COUNT], YGNodeRef node) {
|
||||
YGNodeStyleSetBorder(node, YGEdgeStart, metaProps[META_PROP_LEFT].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeEnd, metaProps[META_PROP_RIGHT].value);
|
||||
if (![[RCTI18nUtil sharedInstance] doesRTLFlipLeftAndRightStyles]) {
|
||||
YGNodeStyleSetBorder(node, YGEdgeStart, metaProps[META_PROP_START].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeEnd, metaProps[META_PROP_END].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeLeft, metaProps[META_PROP_LEFT].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeRight, metaProps[META_PROP_RIGHT].value);
|
||||
} else {
|
||||
const float start = YGFloatIsUndefined(metaProps[META_PROP_START].value) ? metaProps[META_PROP_LEFT].value : metaProps[META_PROP_START].value;
|
||||
const float end = YGFloatIsUndefined(metaProps[META_PROP_END].value) ? metaProps[META_PROP_RIGHT].value : metaProps[META_PROP_END].value;
|
||||
YGNodeStyleSetBorder(node, YGEdgeStart, start);
|
||||
YGNodeStyleSetBorder(node, YGEdgeEnd, end);
|
||||
}
|
||||
YGNodeStyleSetBorder(node, YGEdgeTop, metaProps[META_PROP_TOP].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeBottom, metaProps[META_PROP_BOTTOM].value);
|
||||
YGNodeStyleSetBorder(node, YGEdgeHorizontal, metaProps[META_PROP_HORIZONTAL].value);
|
||||
|
@ -557,6 +568,8 @@ RCT_BORDER_PROPERTY(Top, TOP)
|
|||
RCT_BORDER_PROPERTY(Left, LEFT)
|
||||
RCT_BORDER_PROPERTY(Bottom, BOTTOM)
|
||||
RCT_BORDER_PROPERTY(Right, RIGHT)
|
||||
RCT_BORDER_PROPERTY(Start, START)
|
||||
RCT_BORDER_PROPERTY(End, END)
|
||||
|
||||
// Dimensions
|
||||
#define RCT_DIMENSION_PROPERTY(setProp, getProp, cssProp) \
|
||||
|
|
|
@ -70,8 +70,12 @@
|
|||
@property (nonatomic, assign) CGFloat borderRadius;
|
||||
@property (nonatomic, assign) CGFloat borderTopLeftRadius;
|
||||
@property (nonatomic, assign) CGFloat borderTopRightRadius;
|
||||
@property (nonatomic, assign) CGFloat borderTopStartRadius;
|
||||
@property (nonatomic, assign) CGFloat borderTopEndRadius;
|
||||
@property (nonatomic, assign) CGFloat borderBottomLeftRadius;
|
||||
@property (nonatomic, assign) CGFloat borderBottomRightRadius;
|
||||
@property (nonatomic, assign) CGFloat borderBottomStartRadius;
|
||||
@property (nonatomic, assign) CGFloat borderBottomEndRadius;
|
||||
|
||||
/**
|
||||
* Border colors (actually retained).
|
||||
|
@ -80,6 +84,8 @@
|
|||
@property (nonatomic, assign) CGColorRef borderRightColor;
|
||||
@property (nonatomic, assign) CGColorRef borderBottomColor;
|
||||
@property (nonatomic, assign) CGColorRef borderLeftColor;
|
||||
@property (nonatomic, assign) CGColorRef borderStartColor;
|
||||
@property (nonatomic, assign) CGColorRef borderEndColor;
|
||||
@property (nonatomic, assign) CGColorRef borderColor;
|
||||
|
||||
/**
|
||||
|
@ -89,6 +95,8 @@
|
|||
@property (nonatomic, assign) CGFloat borderRightWidth;
|
||||
@property (nonatomic, assign) CGFloat borderBottomWidth;
|
||||
@property (nonatomic, assign) CGFloat borderLeftWidth;
|
||||
@property (nonatomic, assign) CGFloat borderStartWidth;
|
||||
@property (nonatomic, assign) CGFloat borderEndWidth;
|
||||
@property (nonatomic, assign) CGFloat borderWidth;
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#import "RCTLog.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "UIView+React.h"
|
||||
#import "RCTI18nUtil.h"
|
||||
|
||||
@implementation UIView (RCTViewUnmounting)
|
||||
|
||||
|
@ -110,10 +111,16 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
|||
_borderRightWidth = -1;
|
||||
_borderBottomWidth = -1;
|
||||
_borderLeftWidth = -1;
|
||||
_borderStartWidth = -1;
|
||||
_borderEndWidth = -1;
|
||||
_borderTopLeftRadius = -1;
|
||||
_borderTopRightRadius = -1;
|
||||
_borderTopStartRadius = -1;
|
||||
_borderTopEndRadius = -1;
|
||||
_borderBottomLeftRadius = -1;
|
||||
_borderBottomRightRadius = -1;
|
||||
_borderBottomStartRadius = -1;
|
||||
_borderBottomEndRadius = -1;
|
||||
_borderStyle = RCTBorderStyleSolid;
|
||||
_hitTestEdgeInsets = UIEdgeInsetsZero;
|
||||
|
||||
|
@ -127,7 +134,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:unused)
|
|||
|
||||
- (void)setReactLayoutDirection:(UIUserInterfaceLayoutDirection)layoutDirection
|
||||
{
|
||||
_reactLayoutDirection = layoutDirection;
|
||||
if (_reactLayoutDirection != layoutDirection) {
|
||||
_reactLayoutDirection = layoutDirection;
|
||||
[self.layer setNeedsDisplay];
|
||||
}
|
||||
|
||||
if ([self respondsToSelector:@selector(setSemanticContentAttribute:)]) {
|
||||
self.semanticContentAttribute =
|
||||
|
@ -424,26 +434,77 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:unused)
|
|||
[self.layer setNeedsDisplay];
|
||||
}
|
||||
|
||||
static CGFloat RCTDefaultIfNegativeTo(CGFloat defaultValue, CGFloat x) {
|
||||
return x >= 0 ? x : defaultValue;
|
||||
};
|
||||
|
||||
- (UIEdgeInsets)bordersAsInsets
|
||||
{
|
||||
const CGFloat borderWidth = MAX(0, _borderWidth);
|
||||
const BOOL isRTL = _reactLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft;
|
||||
|
||||
if ([[RCTI18nUtil sharedInstance] doesRTLFlipLeftAndRightStyles]) {
|
||||
const CGFloat borderStartWidth = RCTDefaultIfNegativeTo(_borderLeftWidth, _borderStartWidth);
|
||||
const CGFloat borderEndWidth = RCTDefaultIfNegativeTo(_borderRightWidth, _borderEndWidth);
|
||||
|
||||
const CGFloat directionAwareBorderLeftWidth = isRTL ? borderEndWidth : borderStartWidth;
|
||||
const CGFloat directionAwareBorderRightWidth = isRTL ? borderStartWidth : borderEndWidth;
|
||||
|
||||
return (UIEdgeInsets) {
|
||||
RCTDefaultIfNegativeTo(borderWidth, _borderTopWidth),
|
||||
RCTDefaultIfNegativeTo(borderWidth, directionAwareBorderLeftWidth),
|
||||
RCTDefaultIfNegativeTo(borderWidth, _borderBottomWidth),
|
||||
RCTDefaultIfNegativeTo(borderWidth, directionAwareBorderRightWidth),
|
||||
};
|
||||
}
|
||||
|
||||
const CGFloat directionAwareBorderLeftWidth = isRTL ? _borderEndWidth : _borderStartWidth;
|
||||
const CGFloat directionAwareBorderRightWidth = isRTL ? _borderStartWidth : _borderEndWidth;
|
||||
|
||||
return (UIEdgeInsets) {
|
||||
_borderTopWidth >= 0 ? _borderTopWidth : borderWidth,
|
||||
_borderLeftWidth >= 0 ? _borderLeftWidth : borderWidth,
|
||||
_borderBottomWidth >= 0 ? _borderBottomWidth : borderWidth,
|
||||
_borderRightWidth >= 0 ? _borderRightWidth : borderWidth,
|
||||
RCTDefaultIfNegativeTo(borderWidth, _borderTopWidth),
|
||||
RCTDefaultIfNegativeTo(borderWidth, RCTDefaultIfNegativeTo(_borderLeftWidth, directionAwareBorderLeftWidth)),
|
||||
RCTDefaultIfNegativeTo(borderWidth, _borderBottomWidth),
|
||||
RCTDefaultIfNegativeTo(borderWidth, RCTDefaultIfNegativeTo(_borderRightWidth, directionAwareBorderRightWidth)),
|
||||
};
|
||||
}
|
||||
|
||||
- (RCTCornerRadii)cornerRadii
|
||||
{
|
||||
// Get corner radii
|
||||
const BOOL isRTL = _reactLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft;
|
||||
const CGFloat radius = MAX(0, _borderRadius);
|
||||
const CGFloat topLeftRadius = _borderTopLeftRadius >= 0 ? _borderTopLeftRadius : radius;
|
||||
const CGFloat topRightRadius = _borderTopRightRadius >= 0 ? _borderTopRightRadius : radius;
|
||||
const CGFloat bottomLeftRadius = _borderBottomLeftRadius >= 0 ? _borderBottomLeftRadius : radius;
|
||||
const CGFloat bottomRightRadius = _borderBottomRightRadius >= 0 ? _borderBottomRightRadius : radius;
|
||||
|
||||
CGFloat topLeftRadius;
|
||||
CGFloat topRightRadius;
|
||||
CGFloat bottomLeftRadius;
|
||||
CGFloat bottomRightRadius;
|
||||
|
||||
if ([[RCTI18nUtil sharedInstance] doesRTLFlipLeftAndRightStyles]) {
|
||||
const CGFloat topStartRadius = RCTDefaultIfNegativeTo(_borderTopLeftRadius, _borderTopStartRadius);
|
||||
const CGFloat topEndRadius = RCTDefaultIfNegativeTo(_borderTopRightRadius, _borderTopEndRadius);
|
||||
const CGFloat bottomStartRadius = RCTDefaultIfNegativeTo(_borderBottomLeftRadius, _borderBottomStartRadius);
|
||||
const CGFloat bottomEndRadius = RCTDefaultIfNegativeTo(_borderBottomRightRadius, _borderBottomEndRadius);
|
||||
|
||||
const CGFloat directionAwareTopLeftRadius = isRTL ? topEndRadius : topStartRadius;
|
||||
const CGFloat directionAwareTopRightRadius = isRTL ? topStartRadius : topEndRadius;
|
||||
const CGFloat directionAwareBottomLeftRadius = isRTL ? bottomEndRadius : bottomStartRadius;
|
||||
const CGFloat directionAwareBottomRightRadius = isRTL ? bottomStartRadius : bottomEndRadius;
|
||||
|
||||
topLeftRadius = RCTDefaultIfNegativeTo(radius, directionAwareTopLeftRadius);
|
||||
topRightRadius = RCTDefaultIfNegativeTo(radius, directionAwareTopRightRadius);
|
||||
bottomLeftRadius = RCTDefaultIfNegativeTo(radius, directionAwareBottomLeftRadius);
|
||||
bottomRightRadius = RCTDefaultIfNegativeTo(radius, directionAwareBottomRightRadius);
|
||||
} else {
|
||||
const CGFloat directionAwareTopLeftRadius = isRTL ? _borderTopEndRadius : _borderTopStartRadius;
|
||||
const CGFloat directionAwareTopRightRadius = isRTL ? _borderTopStartRadius : _borderTopEndRadius;
|
||||
const CGFloat directionAwareBottomLeftRadius = isRTL ? _borderBottomEndRadius : _borderBottomStartRadius;
|
||||
const CGFloat directionAwareBottomRightRadius = isRTL ? _borderBottomStartRadius : _borderBottomEndRadius;
|
||||
|
||||
topLeftRadius = RCTDefaultIfNegativeTo(radius, RCTDefaultIfNegativeTo(_borderTopLeftRadius, directionAwareTopLeftRadius));
|
||||
topRightRadius = RCTDefaultIfNegativeTo(radius, RCTDefaultIfNegativeTo(_borderTopRightRadius, directionAwareTopRightRadius));
|
||||
bottomLeftRadius = RCTDefaultIfNegativeTo(radius, RCTDefaultIfNegativeTo(_borderBottomLeftRadius, directionAwareBottomLeftRadius));
|
||||
bottomRightRadius = RCTDefaultIfNegativeTo(radius, RCTDefaultIfNegativeTo(_borderBottomRightRadius, directionAwareBottomRightRadius));
|
||||
}
|
||||
|
||||
// Get scale factors required to prevent radii from overlapping
|
||||
const CGSize size = self.bounds.size;
|
||||
|
@ -463,11 +524,31 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:unused)
|
|||
|
||||
- (RCTBorderColors)borderColors
|
||||
{
|
||||
const BOOL isRTL = _reactLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft;
|
||||
|
||||
if ([[RCTI18nUtil sharedInstance] doesRTLFlipLeftAndRightStyles]) {
|
||||
const CGColorRef borderStartColor = _borderStartColor ?: _borderLeftColor;
|
||||
const CGColorRef borderEndColor = _borderEndColor ?: _borderRightColor;
|
||||
|
||||
const CGColorRef directionAwareBorderLeftColor = isRTL ? borderEndColor : borderStartColor;
|
||||
const CGColorRef directionAwareBorderRightColor = isRTL ? borderStartColor : borderEndColor;
|
||||
|
||||
return (RCTBorderColors){
|
||||
_borderTopColor ?: _borderColor,
|
||||
directionAwareBorderLeftColor ?: _borderColor,
|
||||
_borderBottomColor ?: _borderColor,
|
||||
directionAwareBorderRightColor ?: _borderColor,
|
||||
};
|
||||
}
|
||||
|
||||
const CGColorRef directionAwareBorderLeftColor = isRTL ? _borderEndColor : _borderStartColor;
|
||||
const CGColorRef directionAwareBorderRightColor = isRTL ? _borderStartColor : _borderEndColor;
|
||||
|
||||
return (RCTBorderColors){
|
||||
_borderTopColor ?: _borderColor,
|
||||
_borderLeftColor ?: _borderColor,
|
||||
directionAwareBorderLeftColor ?: _borderLeftColor ?: _borderColor,
|
||||
_borderBottomColor ?: _borderColor,
|
||||
_borderRightColor ?: _borderColor,
|
||||
directionAwareBorderRightColor ?: _borderRightColor ?: _borderColor,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -656,6 +737,8 @@ setBorderColor(Top)
|
|||
setBorderColor(Right)
|
||||
setBorderColor(Bottom)
|
||||
setBorderColor(Left)
|
||||
setBorderColor(Start)
|
||||
setBorderColor(End)
|
||||
|
||||
#pragma mark - Border Width
|
||||
|
||||
|
@ -674,6 +757,8 @@ setBorderWidth(Top)
|
|||
setBorderWidth(Right)
|
||||
setBorderWidth(Bottom)
|
||||
setBorderWidth(Left)
|
||||
setBorderWidth(Start)
|
||||
setBorderWidth(End)
|
||||
|
||||
#pragma mark - Border Radius
|
||||
|
||||
|
@ -690,8 +775,12 @@ setBorderWidth(Left)
|
|||
setBorderRadius()
|
||||
setBorderRadius(TopLeft)
|
||||
setBorderRadius(TopRight)
|
||||
setBorderRadius(TopStart)
|
||||
setBorderRadius(TopEnd)
|
||||
setBorderRadius(BottomLeft)
|
||||
setBorderRadius(BottomRight)
|
||||
setBorderRadius(BottomStart)
|
||||
setBorderRadius(BottomEnd)
|
||||
|
||||
#pragma mark - Border Style
|
||||
|
||||
|
@ -714,6 +803,8 @@ setBorderStyle()
|
|||
CGColorRelease(_borderRightColor);
|
||||
CGColorRelease(_borderBottomColor);
|
||||
CGColorRelease(_borderLeftColor);
|
||||
CGColorRelease(_borderStartColor);
|
||||
CGColorRelease(_borderEndColor);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -246,6 +246,8 @@ RCT_VIEW_BORDER_PROPERTY(Top)
|
|||
RCT_VIEW_BORDER_PROPERTY(Right)
|
||||
RCT_VIEW_BORDER_PROPERTY(Bottom)
|
||||
RCT_VIEW_BORDER_PROPERTY(Left)
|
||||
RCT_VIEW_BORDER_PROPERTY(Start)
|
||||
RCT_VIEW_BORDER_PROPERTY(End)
|
||||
|
||||
#define RCT_VIEW_BORDER_RADIUS_PROPERTY(SIDE) \
|
||||
RCT_CUSTOM_VIEW_PROPERTY(border##SIDE##Radius, CGFloat, RCTView) \
|
||||
|
@ -257,8 +259,12 @@ RCT_CUSTOM_VIEW_PROPERTY(border##SIDE##Radius, CGFloat, RCTView) \
|
|||
|
||||
RCT_VIEW_BORDER_RADIUS_PROPERTY(TopLeft)
|
||||
RCT_VIEW_BORDER_RADIUS_PROPERTY(TopRight)
|
||||
RCT_VIEW_BORDER_RADIUS_PROPERTY(TopStart)
|
||||
RCT_VIEW_BORDER_RADIUS_PROPERTY(TopEnd)
|
||||
RCT_VIEW_BORDER_RADIUS_PROPERTY(BottomLeft)
|
||||
RCT_VIEW_BORDER_RADIUS_PROPERTY(BottomRight)
|
||||
RCT_VIEW_BORDER_RADIUS_PROPERTY(BottomStart)
|
||||
RCT_VIEW_BORDER_RADIUS_PROPERTY(BottomEnd)
|
||||
|
||||
RCT_REMAP_VIEW_PROPERTY(display, reactDisplay, YGDisplay)
|
||||
RCT_REMAP_VIEW_PROPERTY(zIndex, reactZIndex, NSInteger)
|
||||
|
@ -286,6 +292,8 @@ RCT_EXPORT_SHADOW_PROPERTY(borderTopWidth, float)
|
|||
RCT_EXPORT_SHADOW_PROPERTY(borderRightWidth, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(borderBottomWidth, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(borderLeftWidth, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(borderStartWidth, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(borderEndWidth, float)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(borderWidth, float)
|
||||
|
||||
RCT_EXPORT_SHADOW_PROPERTY(marginTop, YGValue)
|
||||
|
|
Loading…
Reference in New Issue