So, I have a CALayer
, which has a mask & I want to add border around this layer's mask. For example, I have set triangle mask to the layer and I want to have border around that layer.
Can anyone please help me to solve this problem?
Swift 4
class CustomView: UIView {
override func draw(_ rect: CGRect) {
super.draw(rect)
self.backgroundColor = UIColor.black
//setup path for mask and border
let halfHeight = self.bounds.height * 0.5
let maskPath = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .bottomRight],
cornerRadii: CGSize(width: halfHeight,
height: halfHeight))
//setup MASK
self.layer.mask = nil;
let maskLayer = CAShapeLayer()
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.cgPath
self.layer.mask = maskLayer
//setup Border for Mask
let borderLayer = CAShapeLayer()
borderLayer.path = maskPath.cgPath
borderLayer.lineWidth = 25
borderLayer.strokeColor = UIColor.red.cgColor
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.frame = self.bounds
self.layer.addSublayer(borderLayer)
}
My approach in swift3.
// Usage:
self.btnGroup.roundCorner([.topRight, .bottomRight], radius: 4.0, borderColor: UIColor.red, borderWidth: 1.0)
// Apply round corner and border. An extension method of UIView.
public func roundCorner(_ corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
let path = UIBezierPath.init(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
let borderPath = UIBezierPath.init(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let borderLayer = CAShapeLayer()
borderLayer.path = borderPath.cgPath
borderLayer.lineWidth = borderWidth
borderLayer.strokeColor = borderColor.cgColor
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.frame = self.bounds
self.layer.addSublayer(borderLayer)
}
Consider this example code:
- (void)drawRect:(CGRect)rect {
CAShapeLayer *maskLayer = [CAShapeLayer layer];
//Modify to your needs
CGFloat maskInsetWidth = 5.0f;
CGFloat maskInsetHeight = 5.0f;
CGFloat maskCornerRadius = 5.0f;
CGFloat borderWidth = 2.0f;
UIColor *borderColor = [UIColor blackColor];
CGRect insetRect = CGRectInset(self.bounds, maskInsetWidth, maskInsetHeight);
insetRect.size.width = MAX(insetRect.size.width, 0);
insetRect.size.height = MAX(insetRect.size.height, 0);
CGPathRef path = [UIBezierPath bezierPathWithRoundedRect:insetRect cornerRadius:maskCornerRadius].CGPath;
if (borderWidth > 0.0f && borderColor != nil) {
CAShapeLayer *borderLayer = [CAShapeLayer layer];
[borderLayer setPath:path];
[borderLayer setLineWidth:borderWidth * 2.0f];
[borderLayer setStrokeColor:borderColor.CGColor];
[borderLayer setFillColor:[UIColor clearColor].CGColor];
borderLayer.frame = self.bounds;
[self.layer addSublayer:borderLayer];
}
[maskLayer setPath:path];
[maskLayer setFillRule:kCAFillRuleEvenOdd];
maskLayer.frame = self.bounds;
[self.layer setMask:maskLayer];
}
Some suggestions:
vImageDilate
family of functions (more complicated, and may run into performance problems).CAShapeLayer
to draw the border.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With