Fabric: Custom border rendering on a separate CALayer
Summary: This diff fixes previously broken custom border rendering. We need a dedicated CALayer for border bitmap in order to fully support all UIView capabilities in case if some subclass uses that. Otherwise, any call of `drawRect:` method can override any content which is stored inside `contents` property of CALayer. Q&A: How does it work in current RN? - It does not. All `drawRect:` methods in RCTView subclasses are dysfunctional. How does text view work in current RN? - RCTTextView does not inherit RCTView, so it does not have this problem. How does text view support custom borders in current RN then? - It does not. Reviewed By: PeteTheHeat Differential Revision: D10228805 fbshipit-source-id: 22bc31f41ab1914a97f3a5981cd1b24ebca725cd
This commit is contained in:
parent
082a869dae
commit
c8b6d606a0
|
@ -20,6 +20,7 @@ using namespace facebook::react;
|
|||
@implementation RCTViewComponentView
|
||||
{
|
||||
UIColor *_backgroundColor;
|
||||
CALayer *_borderLayer;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
|
@ -49,6 +50,10 @@ using namespace facebook::react;
|
|||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
if (_borderLayer) {
|
||||
_borderLayer.frame = self.layer.bounds;
|
||||
}
|
||||
|
||||
if (_contentView) {
|
||||
_contentView.frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame());
|
||||
}
|
||||
|
@ -346,8 +351,11 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) {
|
|||
);
|
||||
|
||||
if (useCoreAnimationBorderRendering) {
|
||||
layer.contents = nil;
|
||||
layer.needsDisplayOnBoundsChange = NO;
|
||||
if (_borderLayer) {
|
||||
[_borderLayer removeFromSuperlayer];
|
||||
_borderLayer = nil;
|
||||
}
|
||||
|
||||
layer.borderWidth = (CGFloat)borderMetrics.borderWidths.left;
|
||||
layer.borderColor = RCTCGColorRefFromSharedColor(borderMetrics.borderColors.left);
|
||||
layer.cornerRadius = (CGFloat)borderMetrics.borderRadii.topLeft;
|
||||
|
@ -355,6 +363,14 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) {
|
|||
_contentView.layer.cornerRadius = (CGFloat)borderMetrics.borderRadii.topLeft;
|
||||
_contentView.layer.masksToBounds = YES;
|
||||
} else {
|
||||
if (!_borderLayer) {
|
||||
_borderLayer = [[CALayer alloc] init];
|
||||
_borderLayer.zPosition = -1024.0f;
|
||||
_borderLayer.frame = layer.bounds;
|
||||
_borderLayer.magnificationFilter = kCAFilterNearest;
|
||||
[layer addSublayer:_borderLayer];
|
||||
}
|
||||
|
||||
layer.backgroundColor = nil;
|
||||
layer.borderWidth = 0;
|
||||
layer.borderColor = nil;
|
||||
|
@ -373,8 +389,7 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) {
|
|||
);
|
||||
|
||||
if (image == nil) {
|
||||
layer.contents = nil;
|
||||
layer.needsDisplayOnBoundsChange = NO;
|
||||
_borderLayer.contents = nil;
|
||||
} else {
|
||||
CGSize imageSize = image.size;
|
||||
UIEdgeInsets imageCapInsets = image.capInsets;
|
||||
|
@ -383,16 +398,14 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) {
|
|||
CGSize {(CGFloat)1.0 / imageSize.width, (CGFloat)1.0 / imageSize.height}
|
||||
};
|
||||
|
||||
layer.contents = (id)image.CGImage;
|
||||
layer.contentsScale = image.scale;
|
||||
layer.needsDisplayOnBoundsChange = YES;
|
||||
layer.magnificationFilter = kCAFilterNearest;
|
||||
_borderLayer.contents = (id)image.CGImage;
|
||||
_borderLayer.contentsScale = image.scale;
|
||||
|
||||
const BOOL isResizable = !UIEdgeInsetsEqualToEdgeInsets(image.capInsets, UIEdgeInsetsZero);
|
||||
if (isResizable) {
|
||||
layer.contentsCenter = contentsCenter;
|
||||
_borderLayer.contentsCenter = contentsCenter;
|
||||
} else {
|
||||
layer.contentsCenter = CGRect { CGPoint {0.0, 0.0}, CGSize {1.0, 1.0}};
|
||||
_borderLayer.contentsCenter = CGRect { CGPoint {0.0, 0.0}, CGSize {1.0, 1.0}};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -420,10 +433,6 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) {
|
|||
layer.cornerRadius = cornerRadius;
|
||||
layer.mask = maskLayer;
|
||||
}
|
||||
|
||||
// After updating `layer`'s parameters we have to redraw on top of it
|
||||
// all custom content (calling `drawRect:` implemented in subclasses).
|
||||
[layer setNeedsDisplay];
|
||||
}
|
||||
|
||||
#pragma mark - Accessibility
|
||||
|
|
Loading…
Reference in New Issue