[React Native] [FRC - Don't accept] View border support
This commit is contained in:
parent
d2206d492d
commit
330c1abbff
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
View
|
||||
} = React;
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
box: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
border1: {
|
||||
borderWidth: 10,
|
||||
borderColor: 'brown',
|
||||
},
|
||||
borderRadius: {
|
||||
borderWidth: 10,
|
||||
borderRadius: 10,
|
||||
borderColor: 'cyan',
|
||||
},
|
||||
border2: {
|
||||
borderWidth: 10,
|
||||
borderTopColor: 'red',
|
||||
borderRightColor: 'yellow',
|
||||
borderBottomColor: 'green',
|
||||
borderLeftColor: 'blue',
|
||||
},
|
||||
border3: {
|
||||
borderColor: 'purple',
|
||||
borderTopWidth: 10,
|
||||
borderRightWidth: 20,
|
||||
borderBottomWidth: 30,
|
||||
borderLeftWidth: 40,
|
||||
},
|
||||
border4: {
|
||||
borderTopWidth: 10,
|
||||
borderTopColor: 'red',
|
||||
borderRightWidth: 20,
|
||||
borderRightColor: 'yellow',
|
||||
borderBottomWidth: 30,
|
||||
borderBottomColor: 'green',
|
||||
borderLeftWidth: 40,
|
||||
borderLeftColor: 'blue',
|
||||
},
|
||||
});
|
||||
|
||||
exports.title = 'Border';
|
||||
exports.description = 'View borders';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Equal-Width / Same-Color',
|
||||
description: 'borderWidth & borderColor',
|
||||
render() {
|
||||
return <View style={[styles.box, styles.border1]} />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Equal-Width / Same-Color',
|
||||
description: 'borderWidth & borderColor',
|
||||
render() {
|
||||
return <View style={[styles.box, styles.borderRadius]} />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Equal-Width Borders',
|
||||
description: 'borderWidth & border*Color',
|
||||
render() {
|
||||
return <View style={[styles.box, styles.border2]} />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Same-Color Borders',
|
||||
description: 'border*Width & borderColor',
|
||||
render() {
|
||||
return <View style={[styles.box, styles.border3]} />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Custom Borders',
|
||||
description: 'border*Width & border*Color',
|
||||
render() {
|
||||
return <View style={[styles.box, styles.border4]} />;
|
||||
}
|
||||
},
|
||||
];
|
|
@ -55,6 +55,7 @@ var APIS = [
|
|||
require('./AlertIOSExample'),
|
||||
require('./AppStateIOSExample'),
|
||||
require('./AsyncStorageExample'),
|
||||
require('./BorderExample'),
|
||||
require('./CameraRollExample.ios'),
|
||||
require('./GeolocationExample'),
|
||||
require('./LayoutExample'),
|
||||
|
|
|
@ -437,9 +437,6 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
|
|||
completion(YES);
|
||||
}
|
||||
|
||||
// TODO: deprecate this
|
||||
[view reactSetBorders];
|
||||
|
||||
// Animate view creation
|
||||
BOOL shouldAnimateCreation = isNew && ![parentsAreNew[ii] boolValue];
|
||||
RCTAnimation *createAnimation = _layoutAnimation.createAnimation;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
RCT_EXPORT_VIEW_PROPERTY(selected, BOOL);
|
||||
RCT_EXPORT_VIEW_PROPERTY(icon, NSString);
|
||||
RCT_REMAP_VIEW_PROPERTY(selectedIcon, barItem.selectedImage, NSString);
|
||||
RCT_REMAP_VIEW_PROPERTY(selectedIcon, barItem.selectedImage, UIImage);
|
||||
RCT_REMAP_VIEW_PROPERTY(badgeValue, barItem.badgeValue, NSString);
|
||||
RCT_CUSTOM_VIEW_PROPERTY(title, NSString, RCTTabBarItem)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,13 @@
|
|||
|
||||
#import "RCTPointerEvents.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, RCTBorderSide) {
|
||||
RCTBorderSideTop,
|
||||
RCTBorderSideRight,
|
||||
RCTBorderSideBottom,
|
||||
RCTBorderSideLeft
|
||||
};
|
||||
|
||||
@protocol RCTAutoInsetsProtocol;
|
||||
|
||||
@interface RCTView : UIView
|
||||
|
@ -48,4 +55,22 @@
|
|||
*/
|
||||
- (void)updateClippedSubviews;
|
||||
|
||||
/**
|
||||
* Border colors.
|
||||
*/
|
||||
@property (nonatomic, assign) CGColorRef borderTopColor;
|
||||
@property (nonatomic, assign) CGColorRef borderRightColor;
|
||||
@property (nonatomic, assign) CGColorRef borderBottomColor;
|
||||
@property (nonatomic, assign) CGColorRef borderLeftColor;
|
||||
@property (nonatomic, assign) CGColorRef borderColor;
|
||||
|
||||
/**
|
||||
* Border widths.
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat borderTopWidth;
|
||||
@property (nonatomic, assign) CGFloat borderRightWidth;
|
||||
@property (nonatomic, assign) CGFloat borderBottomWidth;
|
||||
@property (nonatomic, assign) CGFloat borderLeftWidth;
|
||||
@property (nonatomic, assign) CGFloat borderWidth;
|
||||
|
||||
@end
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#import "RCTLog.h"
|
||||
#import "UIView+ReactKit.h"
|
||||
|
||||
static const RCTBorderSide RCTBorderSideCount = 4;
|
||||
|
||||
@implementation UIView (RCTViewUnmounting)
|
||||
|
||||
- (void)react_remountAllSubviews
|
||||
|
@ -91,6 +93,8 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
|||
@implementation RCTView
|
||||
{
|
||||
NSMutableArray *_reactSubviews;
|
||||
CAShapeLayer *_borderLayers[RCTBorderSideCount];
|
||||
CGFloat _borderWidths[RCTBorderSideCount];
|
||||
}
|
||||
|
||||
- (NSString *)accessibilityLabel
|
||||
|
@ -106,7 +110,7 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
|||
_pointerEvents = pointerEvents;
|
||||
self.userInteractionEnabled = (pointerEvents != RCTPointerEventsNone);
|
||||
if (pointerEvents == RCTPointerEventsBoxNone) {
|
||||
self.accessibilityViewIsModal = NO; // TODO: find out what this is for
|
||||
self.accessibilityViewIsModal = NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,9 +372,193 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
|||
// to updateClippedSubviews manually after loading
|
||||
|
||||
[super layoutSubviews];
|
||||
|
||||
if (_reactSubviews) {
|
||||
[self updateClippedSubviews];
|
||||
}
|
||||
|
||||
for (RCTBorderSide side = 0; side < RCTBorderSideCount; side++) {
|
||||
if (_borderLayers[side]) [self updatePathForShapeLayerForSide:side];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)layoutSublayersOfLayer:(CALayer *)layer
|
||||
{
|
||||
[super layoutSublayersOfLayer:layer];
|
||||
|
||||
const CGRect bounds = layer.bounds;
|
||||
for (RCTBorderSide side = 0; side < RCTBorderSideCount; side++) {
|
||||
_borderLayers[side].frame = bounds;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)getTrapezoidPoints:(CGPoint[4])outPoints forSide:(RCTBorderSide)side
|
||||
{
|
||||
const CGRect bounds = self.layer.bounds;
|
||||
const CGFloat minX = CGRectGetMinX(bounds);
|
||||
const CGFloat maxX = CGRectGetMaxX(bounds);
|
||||
const CGFloat minY = CGRectGetMinY(bounds);
|
||||
const CGFloat maxY = CGRectGetMaxY(bounds);
|
||||
|
||||
#define BW(SIDE) [self borderWidthForSide:RCTBorderSide##SIDE]
|
||||
|
||||
switch (side) {
|
||||
case RCTBorderSideRight:
|
||||
outPoints[0] = CGPointMake(maxX - BW(Right), maxY - BW(Bottom));
|
||||
outPoints[1] = CGPointMake(maxX - BW(Right), minY + BW(Top));
|
||||
outPoints[2] = CGPointMake(maxX, minY);
|
||||
outPoints[3] = CGPointMake(maxX, maxY);
|
||||
break;
|
||||
case RCTBorderSideBottom:
|
||||
outPoints[0] = CGPointMake(minX + BW(Left), maxY - BW(Bottom));
|
||||
outPoints[1] = CGPointMake(maxX - BW(Right), maxY - BW(Bottom));
|
||||
outPoints[2] = CGPointMake(maxX, maxY);
|
||||
outPoints[3] = CGPointMake(minX, maxY);
|
||||
break;
|
||||
case RCTBorderSideLeft:
|
||||
outPoints[0] = CGPointMake(minX + BW(Left), minY + BW(Top));
|
||||
outPoints[1] = CGPointMake(minX + BW(Left), maxY - BW(Bottom));
|
||||
outPoints[2] = CGPointMake(minX, maxY);
|
||||
outPoints[3] = CGPointMake(minX, minY);
|
||||
break;
|
||||
case RCTBorderSideTop:
|
||||
outPoints[0] = CGPointMake(maxX - BW(Right), minY + BW(Top));
|
||||
outPoints[1] = CGPointMake(minX + BW(Left), minY + BW(Top));
|
||||
outPoints[2] = CGPointMake(minX, minY);
|
||||
outPoints[3] = CGPointMake(maxX, minY);
|
||||
break;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CAShapeLayer *)createShapeLayerIfNotExistsForSide:(RCTBorderSide)side
|
||||
{
|
||||
CAShapeLayer *borderLayer = _borderLayers[side];
|
||||
if (!borderLayer) {
|
||||
borderLayer = [CAShapeLayer layer];
|
||||
borderLayer.fillColor = self.layer.borderColor;
|
||||
[self.layer addSublayer:borderLayer];
|
||||
_borderLayers[side] = borderLayer;
|
||||
}
|
||||
return borderLayer;
|
||||
}
|
||||
|
||||
- (void)updatePathForShapeLayerForSide:(RCTBorderSide)side
|
||||
{
|
||||
CAShapeLayer *borderLayer = [self createShapeLayerIfNotExistsForSide:side];
|
||||
|
||||
CGPoint trapezoidPoints[4];
|
||||
[self getTrapezoidPoints:trapezoidPoints forSide:side];
|
||||
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGPathAddLines(path, NULL, trapezoidPoints, 4);
|
||||
CGPathCloseSubpath(path);
|
||||
borderLayer.path = path;
|
||||
CGPathRelease(path);
|
||||
}
|
||||
|
||||
- (void)updateBorderLayers
|
||||
{
|
||||
BOOL widthsAndColorsSame = YES;
|
||||
CGFloat width = _borderWidths[0];
|
||||
CGColorRef color = _borderLayers[0].fillColor;
|
||||
for (RCTBorderSide side = 1; side < RCTBorderSideCount; side++) {
|
||||
CAShapeLayer *layer = _borderLayers[side];
|
||||
if (_borderWidths[side] != width || (layer && !CGColorEqualToColor(layer.fillColor, color))) {
|
||||
widthsAndColorsSame = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (widthsAndColorsSame) {
|
||||
|
||||
// Set main layer border
|
||||
if (width) {
|
||||
_borderWidth = self.layer.borderWidth = width;
|
||||
}
|
||||
if (color) {
|
||||
self.layer.borderColor = color;
|
||||
}
|
||||
|
||||
// Remove border layers
|
||||
for (RCTBorderSide side = 0; side < RCTBorderSideCount; side++) {
|
||||
[_borderLayers[side] removeFromSuperlayer];
|
||||
_borderLayers[side] = nil;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Clear main layer border
|
||||
self.layer.borderWidth = 0;
|
||||
|
||||
// Set up border layers
|
||||
for (RCTBorderSide side = 0; side < RCTBorderSideCount; side++) {
|
||||
[self updatePathForShapeLayerForSide:side];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (CGFloat)borderWidthForSide:(RCTBorderSide)side
|
||||
{
|
||||
return _borderWidths[side] ?: _borderWidth;
|
||||
}
|
||||
|
||||
- (void)setBorderWidth:(CGFloat)width forSide:(RCTBorderSide)side
|
||||
{
|
||||
_borderWidths[side] = width;
|
||||
[self updateBorderLayers];
|
||||
}
|
||||
|
||||
#define BORDER_WIDTH(SIDE) \
|
||||
- (CGFloat)border##SIDE##Width { return [self borderWidthForSide:RCTBorderSide##SIDE]; } \
|
||||
- (void)setBorder##SIDE##Width:(CGFloat)width { [self setBorderWidth:width forSide:RCTBorderSide##SIDE]; }
|
||||
|
||||
BORDER_WIDTH(Top)
|
||||
BORDER_WIDTH(Right)
|
||||
BORDER_WIDTH(Bottom)
|
||||
BORDER_WIDTH(Left)
|
||||
|
||||
- (CGColorRef)borderColorForSide:(RCTBorderSide)side
|
||||
{
|
||||
return _borderLayers[side].fillColor ?: self.layer.borderColor;
|
||||
}
|
||||
|
||||
- (void)setBorderColor:(CGColorRef)color forSide:(RCTBorderSide)side
|
||||
{
|
||||
[self createShapeLayerIfNotExistsForSide:side].fillColor = color;
|
||||
[self updateBorderLayers];
|
||||
}
|
||||
|
||||
#define BORDER_COLOR(SIDE) \
|
||||
- (CGColorRef)border##SIDE##Color { return [self borderColorForSide:RCTBorderSide##SIDE]; } \
|
||||
- (void)setBorder##SIDE##Color:(CGColorRef)color { [self setBorderColor:color forSide:RCTBorderSide##SIDE]; }
|
||||
|
||||
BORDER_COLOR(Top)
|
||||
BORDER_COLOR(Right)
|
||||
BORDER_COLOR(Bottom)
|
||||
BORDER_COLOR(Left)
|
||||
|
||||
- (void)setBorderWidth:(CGFloat)borderWidth
|
||||
{
|
||||
_borderWidth = borderWidth;
|
||||
for (RCTBorderSide side = 0; side < RCTBorderSideCount; side++) {
|
||||
_borderWidths[side] = borderWidth;
|
||||
}
|
||||
[self updateBorderLayers];
|
||||
}
|
||||
|
||||
- (void)setBorderColor:(CGColorRef)borderColor
|
||||
{
|
||||
self.layer.borderColor = borderColor;
|
||||
for (RCTBorderSide side = 0; side < RCTBorderSideCount; side++) {
|
||||
_borderLayers[side].fillColor = borderColor;
|
||||
}
|
||||
[self updateBorderLayers];
|
||||
}
|
||||
|
||||
- (CGColorRef)borderColor
|
||||
{
|
||||
return self.layer.borderColor;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -81,9 +81,6 @@ RCT_REMAP_VIEW_PROPERTY(shadowColor, layer.shadowColor, CGColor);
|
|||
RCT_REMAP_VIEW_PROPERTY(shadowOffset, layer.shadowOffset, CGSize);
|
||||
RCT_REMAP_VIEW_PROPERTY(shadowOpacity, layer.shadowOpacity, CGFloat)
|
||||
RCT_REMAP_VIEW_PROPERTY(shadowRadius, layer.shadowRadius, CGFloat)
|
||||
RCT_REMAP_VIEW_PROPERTY(borderColor, layer.borderColor, CGColor);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderRadius, layer.cornerRadius, CGFloat)
|
||||
RCT_REMAP_VIEW_PROPERTY(borderWidth, layer.borderWidth, CGFloat)
|
||||
RCT_REMAP_VIEW_PROPERTY(transformMatrix, layer.transform, CATransform3D)
|
||||
RCT_CUSTOM_VIEW_PROPERTY(overflow, css_overflow, RCTView)
|
||||
{
|
||||
|
@ -122,6 +119,42 @@ RCT_CUSTOM_VIEW_PROPERTY(removeClippedSubviews, BOOL, RCTView)
|
|||
view.removeClippedSubviews = json ? [RCTConvert BOOL:json] : defaultView.removeClippedSubviews;
|
||||
}
|
||||
}
|
||||
RCT_REMAP_VIEW_PROPERTY(borderRadius, layer.cornerRadius, CGFloat)
|
||||
RCT_CUSTOM_VIEW_PROPERTY(borderColor, CGColor, RCTView)
|
||||
{
|
||||
if ([view respondsToSelector:@selector(setBorderColor:)]) {
|
||||
view.borderColor = json ? [RCTConvert CGColor:json] : defaultView.borderColor;
|
||||
} else {
|
||||
view.layer.borderColor = json ? [RCTConvert CGColor:json] : defaultView.layer.borderColor;
|
||||
}
|
||||
}
|
||||
RCT_CUSTOM_VIEW_PROPERTY(borderWidth, CGFloat, RCTView)
|
||||
{
|
||||
if ([view respondsToSelector:@selector(setBorderWidth:)]) {
|
||||
view.borderWidth = json ? [RCTConvert CGFloat:json] : defaultView.borderWidth;
|
||||
} else {
|
||||
view.layer.borderWidth = json ? [RCTConvert CGFloat:json] : defaultView.layer.borderWidth;
|
||||
}
|
||||
}
|
||||
|
||||
#define RCT_VIEW_BORDER_PROPERTY(SIDE) \
|
||||
RCT_CUSTOM_VIEW_PROPERTY(border##SIDE##Width, CGFloat, RCTView) \
|
||||
{ \
|
||||
if ([view respondsToSelector:@selector(setBorder##SIDE##Width:)]) { \
|
||||
view.border##SIDE##Width = json ? [RCTConvert CGFloat:json] : defaultView.border##SIDE##Width; \
|
||||
} \
|
||||
} \
|
||||
RCT_CUSTOM_VIEW_PROPERTY(border##SIDE##Color, UIColor, RCTView) \
|
||||
{ \
|
||||
if ([view respondsToSelector:@selector(setBorder##SIDE##Color:)]) { \
|
||||
view.border##SIDE##Color = json ? [RCTConvert CGColor:json] : defaultView.border##SIDE##Color; \
|
||||
} \
|
||||
}
|
||||
|
||||
RCT_VIEW_BORDER_PROPERTY(Top)
|
||||
RCT_VIEW_BORDER_PROPERTY(Right)
|
||||
RCT_VIEW_BORDER_PROPERTY(Bottom)
|
||||
RCT_VIEW_BORDER_PROPERTY(Left)
|
||||
|
||||
#pragma mark - ShadowView properties
|
||||
|
||||
|
@ -169,15 +202,4 @@ RCT_CUSTOM_SHADOW_PROPERTY(backgroundColor, UIColor, RCTShadowView)
|
|||
view.isBGColorExplicitlySet = json ? YES : defaultView.isBGColorExplicitlySet;
|
||||
}
|
||||
|
||||
// Border properties - to be deprecated
|
||||
|
||||
RCT_REMAP_VIEW_PROPERTY(borderTopWidth, reactBorderTop.width, CGFloat);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderRightWidth, reactBorderRight.width, CGFloat);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderBottomWidth, reactBorderBottom.width, CGFloat);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderLeftWidth, reactBorderLeft.width, CGFloat);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderTopColor, reactBorderTop.color, UIColor);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderRightColor, reactBorderRight.color, UIColor);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderBottomColor, reactBorderBottom.color, UIColor);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderLeftColor, reactBorderLeft.color, UIColor);
|
||||
|
||||
@end
|
||||
|
|
|
@ -42,12 +42,3 @@
|
|||
- (BOOL)reactRespondsToTouch:(UITouch *)touch;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIView (ReactKitBorders)
|
||||
|
||||
/**
|
||||
* Borders stuff - pay no attention to this, it's going away (#6548297)
|
||||
*/
|
||||
- (void)reactSetBorders;
|
||||
|
||||
@end
|
||||
|
|
|
@ -119,156 +119,3 @@
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Borders
|
||||
|
||||
// Note: the value of this enum determines their relative zPosition
|
||||
typedef NS_ENUM(NSUInteger, RCTBorderSide) {
|
||||
RCTBorderSideTop = 0,
|
||||
RCTBorderSideRight = 1,
|
||||
RCTBorderSideBottom = 2,
|
||||
RCTBorderSideLeft = 3
|
||||
};
|
||||
|
||||
@interface RCTSingleSidedBorder : NSObject
|
||||
|
||||
@property (nonatomic, readwrite, assign) CGFloat width;
|
||||
@property (nonatomic, readwrite, strong) UIColor *color;
|
||||
@property (nonatomic, readonly, assign) RCTBorderSide side;
|
||||
|
||||
- (instancetype)initWithSide:(RCTBorderSide)side superlayer:(CALayer *)superlayer;
|
||||
|
||||
- (void)superLayerBoundsDidChange;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTSingleSidedBorder
|
||||
{
|
||||
CALayer *_borderLayer;
|
||||
}
|
||||
|
||||
- (instancetype)initWithSide:(RCTBorderSide)side superlayer:(CALayer *)superlayer
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_side = side;
|
||||
|
||||
_borderLayer = [CALayer layer];
|
||||
_borderLayer.delegate = self;
|
||||
_borderLayer.zPosition = INT_MAX - _side;
|
||||
|
||||
[superlayer insertSublayer:_borderLayer atIndex:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
_borderLayer.delegate = nil;
|
||||
}
|
||||
|
||||
- (void)setWidth:(CGFloat)width
|
||||
{
|
||||
_width = width;
|
||||
[_borderLayer setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setColor:(UIColor *)color
|
||||
{
|
||||
_color = color;
|
||||
_borderLayer.backgroundColor = _color.CGColor;
|
||||
[_borderLayer setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)superLayerBoundsDidChange
|
||||
{
|
||||
[_borderLayer setNeedsLayout];
|
||||
}
|
||||
|
||||
#pragma mark - CALayerDelegate
|
||||
|
||||
- (void)layoutSublayersOfLayer:(CALayer *)layer
|
||||
{
|
||||
CGSize superlayerSize = layer.superlayer.frame.size;
|
||||
|
||||
CGFloat xPosition = 0.0f;
|
||||
CGFloat yPosition = 0.0f;
|
||||
|
||||
// Note: we ensure side layers are below top & bottom for snapshot test consistency
|
||||
|
||||
switch (self.side) {
|
||||
case RCTBorderSideTop:
|
||||
layer.frame = CGRectMake(xPosition, yPosition, superlayerSize.width, self.width);
|
||||
break;
|
||||
case RCTBorderSideRight:
|
||||
xPosition = superlayerSize.width - self.width;
|
||||
layer.frame = CGRectMake(xPosition, yPosition, self.width, superlayerSize.height);
|
||||
[layer.superlayer insertSublayer:layer atIndex:0];
|
||||
break;
|
||||
case RCTBorderSideBottom:
|
||||
yPosition = superlayerSize.height - self.width;
|
||||
layer.frame = CGRectMake(xPosition, yPosition, superlayerSize.width, self.width);
|
||||
break;
|
||||
case RCTBorderSideLeft:
|
||||
layer.frame = CGRectMake(xPosition, yPosition, self.width, superlayerSize.height);
|
||||
[layer.superlayer insertSublayer:layer atIndex:0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Disable animations for layer
|
||||
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
|
||||
{
|
||||
return (id)[NSNull null];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIView (ReactKitBorders)
|
||||
|
||||
- (void)reactSetBorders
|
||||
{
|
||||
NSMutableDictionary *borders = objc_getAssociatedObject(self, @selector(_createOrGetBorderWithSide:));
|
||||
if (borders) {
|
||||
for (RCTSingleSidedBorder *border in [borders allValues]) {
|
||||
[border superLayerBoundsDidChange];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (RCTSingleSidedBorder *)reactBorderTop
|
||||
{
|
||||
return [self _createOrGetBorderWithSide:RCTBorderSideTop];
|
||||
}
|
||||
|
||||
- (RCTSingleSidedBorder *)reactBorderRight
|
||||
{
|
||||
return [self _createOrGetBorderWithSide:RCTBorderSideRight];
|
||||
}
|
||||
|
||||
- (RCTSingleSidedBorder *)reactBorderBottom
|
||||
{
|
||||
return [self _createOrGetBorderWithSide:RCTBorderSideBottom];
|
||||
}
|
||||
|
||||
- (RCTSingleSidedBorder *)reactBorderLeft
|
||||
{
|
||||
return [self _createOrGetBorderWithSide:RCTBorderSideLeft];
|
||||
}
|
||||
|
||||
- (RCTSingleSidedBorder *)_createOrGetBorderWithSide:(RCTBorderSide)side
|
||||
{
|
||||
NSMutableDictionary *borders = objc_getAssociatedObject(self, _cmd);
|
||||
if (!borders) {
|
||||
borders = [[NSMutableDictionary alloc] init];
|
||||
objc_setAssociatedObject(self, _cmd, borders, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
RCTSingleSidedBorder *border = [borders objectForKey:@(side)];
|
||||
if (!border) {
|
||||
border = [[RCTSingleSidedBorder alloc] initWithSide:side superlayer:self.layer];
|
||||
[borders setObject:border forKey:@(side)];
|
||||
}
|
||||
return border;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue