我的申请主要是以圆形和边界为基础的。
我使用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
提供更好的结果吗?
答案 0 :(得分:14)
我尝试了很多解决方案并使用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
:Thinking like a Bézier path
我从这两个链接获得了大部分代码:
注意:这是类别方法,因此自我表示调用此方法的视图。像UIButton,UIImageView等。
答案 1 :(得分:9)
这是我的Swift版@ CRDave' s answer作为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)
}
}
答案 2 :(得分:6)
这是Kamil Nomtek.com's answer更新为 Swift 3 + 并进行了一些改进(主要是语义/命名和使用类协议)。
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)
}
}
答案 3 :(得分:3)
CRDave的答案效果很好但有一个缺陷:当多次调用大小变化时,它会不断添加图层。而是应该更新以前的图层 请参阅下面的更新ObjC版本。对于swift,请相应调整。
// UIView+Border.h
#import <UIKit/UIKit.h>
@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
答案 4 :(得分:0)
de.'s answer worked much better for me而不是CRDave的答案。
我必须从Swift进行翻译,所以我想继续翻译并发布:
extension UIView {
func giveBorderWithCornerRadius(cornerRadius r: CGFloat, borderColor c: UIColor, strokeWidth w: CGFloat) {
let rect = self.bounds
let maskPath = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: r, height: r))
let maskLayer = CAShapeLayer()
maskLayer.frame = rect
maskLayer.path = maskPath.cgPath
self.layer.mask = maskLayer
let borderPath = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: r, height: r))
let layerName = "border_layer"
var borderLayer: CAShapeLayer? = self.layer.sublayers?.filter({ (c) -> Bool in
if c.name == layerName {
return true
} else {
return false
}
}).first as? CAShapeLayer
if borderLayer == nil {
borderLayer = CAShapeLayer()
borderLayer!.name = layerName
self.layer.addSublayer(borderLayer!)
}
borderLayer!.frame = rect
borderLayer!.path = borderPath.cgPath
borderLayer!.strokeColor = c.cgColor
borderLayer!.fillColor = UIColor.clear.cgColor
borderLayer!.lineWidth = w
}
}
我正在从layoutSubviews()
调用该方法
答案 5 :(得分:-3)
删除
button.layer.borderWidth = 0.3;
button.layer.borderColor = [[UIColor blueMain] CGColor];