带边框的cornerRadius:边界周围有毛刺
我的申请大多是圆形和边界的。
我使用UIView
的图层属性来给出角半径和边框。
但我面临的问题是角落不清楚。
我得到以下结果:
的UIButton
的UIImageView
您可以观察到白色或灰色边框周围的细边框线。
这是我的代码:
button.layer.borderWidth = 2.0; button.layer.borderColor = [[UIColor whiteColor] CGColor]; button.layer.cornerRadius = 4; button.clipsToBounds = YES;
我已经寻求解决这个问题,但我没有成功。
我尝试过button.layer.masksToBounds = YES
,但没有效果。
我错过了什么吗? 还是有其他方法可以比CALayer
更好的结果?
我尝试了很多解决方案并使用UIBezierPath
结束。
我创建UIView
类别并添加方法来制作圆形矩形和边框。
这是该类别的方法:
- (void)giveBorderWithCornerRadious:(CGFloat)radius borderColor:(UIColor *)borderColor andBorderWidth:(CGFloat)borderWidth { CGRect rect = self.bounds; //Make round // Create the path for to make circle UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)]; // Create the shape layer and set its path CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.frame = rect; maskLayer.path = maskPath.CGPath; // Set the newly created shape layer as the mask for the view's layer self.layer.mask = maskLayer; //Give Border //Create path for border UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)]; // Create the shape layer and set its path CAShapeLayer *borderLayer = [CAShapeLayer layer]; borderLayer.frame = rect; borderLayer.path = borderPath.CGPath; borderLayer.strokeColor = [UIColor whiteColor].CGColor; borderLayer.fillColor = [UIColor clearColor].CGColor; borderLayer.lineWidth = borderWidth; //Add this layer to give border. [[self layer] addSublayer:borderLayer]; }
我从这篇惊人的文章中得到了使用UIBezierPath
想法: 像Bézier路径一样思考
我从这两个链接获得了大部分代码:
- UIView类别用于舍入您想要的角落,而不是像CALayer cornerRadius一样。
- 如何在UIBezierPath上获取边框
注意:这是类别方法,因此自我表示调用此方法的视图。 像UIButton,UIImageView等。
这是我的Swift版本的@ CRDave的答案作为UIView的扩展:
protocol CornerRadius { func makeBorderWithCornerRadius(radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) } extension UIView: CornerRadius { func makeBorderWithCornerRadius(radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) { let rect = self.bounds; let maskPath = UIBezierPath(roundedRect: rect, byRoundingCorners: .AllCorners, cornerRadii: CGSize(width: radius, height: radius)) // Create the shape layer and set its path let maskLayer = CAShapeLayer() maskLayer.frame = rect maskLayer.path = maskPath.CGPath // Set the newly created shape layer as the mask for the view's layer self.layer.mask = maskLayer //Create path for border let borderPath = UIBezierPath(roundedRect: rect, byRoundingCorners: .AllCorners, cornerRadii: CGSize(width: radius, height: radius)) // Create the shape layer and set its path let borderLayer = CAShapeLayer() borderLayer.frame = rect borderLayer.path = borderPath.CGPath borderLayer.strokeColor = borderColor.CGColor borderLayer.fillColor = UIColor.clearColor().CGColor borderLayer.lineWidth = borderWidth * UIScreen.mainScreen().scale //Add this layer to give border. self.layer.addSublayer(borderLayer) } }
这是Kamil Nomtek.com的答案更新为Swift 3/4并进行了一些改进(主要是语义/命名和使用类协议)。
protocol RoundedBorderProtocol: class { func makeBorder(with radius: CGFloat, borderWidth: CGFloat, borderColor: UIColor) } extension UIView: RoundedBorderProtocol { func makeBorder(with radius: CGFloat, borderWidth: CGFloat, borderColor: UIColor) { let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: radius, height: radius)) // Create the shape layer and set its path let maskLayer = CAShapeLayer() maskLayer.frame = bounds maskLayer.path = maskPath.cgPath // Set the newly created shape layer as the mask for the view's layer layer.mask = maskLayer //Create path for border let borderPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: radius, height: radius)) // Create the shape layer and set its path let borderLayer = CAShapeLayer() borderLayer.frame = bounds borderLayer.path = borderPath.cgPath borderLayer.strokeColor = borderColor.cgColor borderLayer.fillColor = UIColor.clear.cgColor //The border is in the center of the path, so only the inside is visible. //Since only half of the line is visible, we need to multiply our width by 2. borderLayer.lineWidth = borderWidth * 2 //Add this layer to display the border layer.addSublayer(borderLayer) } }
CRDave的答案效果很好但有一个缺陷:当多次调用大小变化时,它会不断添加图层。 而是应该更新以前的图层。
请参阅下面的更新ObjC版本。 对于swift,请相应调整。
// UIView+Border.h #import @interface UIView (Border) - (void)setBorderWithCornerRadius:(CGFloat)radius color:(UIColor *)borderColor width:(CGFloat)borderWidth; @end // UIView+Border.m #import "UIView+Border.h" @implementation UIView (Border) - (void)setBorderWithCornerRadius:(CGFloat)radius color:(UIColor *)borderColor width:(CGFloat)borderWidth { CGRect rect = self.bounds; //Make round // Create the path for to make circle UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)]; // Create the shape layer and set its path CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.frame = rect; maskLayer.path = maskPath.CGPath; // Set the newly created shape layer as the mask for the view's layer self.layer.mask = maskLayer; //Give Border //Create path for border UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)]; // Create the shape layer and set its path NSString *layerName = @"ig_border_layer"; CAShapeLayer *borderLayer = (CAShapeLayer *)[[[self.layer sublayers] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name == %@", layerName]] firstObject]; if (!borderLayer) { borderLayer = [CAShapeLayer layer]; [borderLayer setName:layerName]; //Add this layer to give border. [[self layer] addSublayer:borderLayer]; } borderLayer.frame = rect; borderLayer.path = borderPath.CGPath; borderLayer.strokeColor = [UIColor whiteColor].CGColor; borderLayer.fillColor = [UIColor clearColor].CGColor; borderLayer.lineWidth = borderWidth; } @end
删除
button.layer.borderWidth = 0.3; button.layer.borderColor = [[UIColor blueMain] CGColor];