UIView 的圆顶角并添加边框

Posted

技术标签:

【中文标题】UIView 的圆顶角并添加边框【英文标题】:Round top corners of a UIView and add border 【发布时间】:2014-03-14 16:08:14 【问题描述】:

我在进行圆角处理的类别中有以下代码。我也想画个边框。但边角的圆角部分不显示边框。

这里是代码

- (void) roundTopCorners:(CGFloat) radius

    self.layer.masksToBounds = YES;

    CGRect bounds = self.bounds;
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(radius, radius)];

    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = bounds;
    maskLayer.path = maskPath.CGPath;
    maskLayer.strokeColor = [UIColor redColor].CGColor;

    self.layer.mask = maskLayer;

【问题讨论】:

"请注意,如果您尝试在动态调整大小的视图(例如响应自动旋转)上使用这种框架样式,则必须更加小心,因为图层可以'不要利用自动布局。在这种情况下,您最好的解决方案可能是创建一个自定义 UITextField 并实现 layerClass 以返回一个自定义图层类,该类可以动态调整类似于上面创建的图层的大小。@David Berry“实际上并不那么棘手,如果你想调整所有这些层的大小,只需将所有代码放在 viewDidAppear 中,它就可以工作! 【参考方案1】:

不绘制遮罩层,仅用于计算遮罩。试试:

-(void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius

    CGRect bounds = self.bounds;
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds
                                                   byRoundingCorners:corners
                                                         cornerRadii:CGSizeMake(radius, radius)];

    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = bounds;
    maskLayer.path = maskPath.CGPath;

    self.layer.mask = maskLayer;

    CAShapeLayer*   frameLayer = [CAShapeLayer layer];
    frameLayer.frame = bounds;
    frameLayer.path = maskPath.CGPath;
    frameLayer.strokeColor = [UIColor redColor].CGColor;
    frameLayer.fillColor = nil;

    [self.layer addSublayer:frameLayer];


-(void)roundTopCornersRadius:(CGFloat)radius

    [self roundCorners:(UIRectCornerTopLeft|UIRectCornerTopRight) radius:radius];


-(void)roundBottomCornersRadius:(CGFloat)radius

    [self roundCorners:(UIRectCornerBottomLeft|UIRectCornerBottomRight) radius:radius];

您当前看到的框架是 UITextField 的正常框架,因此请将框架样式设置为无。您还必须调整插图以弥补框架样式设置为 none 时通常没有插图这一事实。

【讨论】:

请注意,如果您尝试在动态调整大小(例如响应自动旋转)的视图上使用这种框架样式,则必须更加小心,因为图层可以' t 利用自动布局。在这种情况下,您最好的解决方案可能是创建一个自定义 UITextField 并实现 layerClass 以返回一个自定义图层类,该类可以动态调整图层的大小,类似于上面创建的图层。 这是一个好方法。但是,边框不会是正确的厚度。这是因为边框的描边一半在蒙版之内,一半在蒙版之外。很容易修复 - 只需添加以下内容:frameLayer.lineWidth = borderWidth*2; 其中borderWidth 是您想要的边框宽度。 @BooTooMany 在某些时候有类似的东西来解释线宽。我想我实际上是在适当的量内插入路径,但是将厚度加倍的效果大致相同并且更简单。 如何在uitableviewcell中调用这些方法【参考方案2】:

David Berry 回答的 Swift 版本:

func roundCorners(corners:UIRectCorner, radius:CGFloat) 
    let bounds = self.bounds

    let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSizeMake(radius, radius))

    let maskLayer = CAShapeLayer()
    maskLayer.frame = bounds
    maskLayer.path = maskPath.CGPath

    self.layer.mask = maskLayer

    let frameLayer = CAShapeLayer()
    frameLayer.frame = bounds
    frameLayer.path = maskPath.CGPath
    frameLayer.strokeColor = UIColor.redColor().CGColor
    frameLayer.fillColor = nil

    self.layer.addSublayer(frameLayer)


func roundTopCornersRadius(radius:CGFloat) 
    self.roundCorners([UIRectCorner.TopLeft, UIRectCorner.TopRight], radius:radius)


func roundBottomCornersRadius(radius:CGFloat) 
    self.roundCorners([UIRectCorner.BottomLeft, UIRectCorner.BottomRight], radius:radius)

【讨论】:

很棒的东西。干杯。【参考方案3】:

这可能是一个很晚的答案,但我只想分享我根据不同人对不同类似问题的答案提出的解决方案。我从上面 Vojtech 的回答中得到了很大的帮助。

extension UIView 
    func EZRoundCorners(corners:UIRectCorner, radius: CGFloat) -> CAShapeLayer 
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.CGPath
        self.layer.mask = mask
        return mask
    

    func EZRoundCornersWithBorder(corners:UIRectCorner, radius:CGFloat, color:UIColor, width:CGFloat) -> CAShapeLayer 

        let mask = self.EZRoundCorners(corners, radius: radius)

        // Add border
        let borderLayer = EZCALayer()
        borderLayer.path = mask.path // Reuse the Bezier path
        borderLayer.fillColor = UIColor.clearColor().CGColor
        borderLayer.strokeColor = color.CGColor
        borderLayer.lineWidth = width
        borderLayer.frame = self.bounds
        self.layer.addSublayer(borderLayer)
        return borderLayer
    

    func removeEZLayers () 
        for layer in self.layer.sublayers! 
            if layer is EZCALayer 
                layer.removeFromSuperlayer()
            
        
    


class EZCALayer : CAShapeLayer 

我从 CAShapeLayer 继承,所以如果我不想再使用它们,我可以删除边框子层。

【讨论】:

【参考方案4】:
      label.layer.cornerRadius = 3.0 
     label.layer.maskedCorners = [.layerMinXMinYCorner,.layerMinXMaxYCorner]//round top left and bottom left corners

来源:https://www.hackingwithswift.com/example-code/calayer/how-to-round-only-specific-corners-using-maskedcorners

Image of working solution

【讨论】:

以上是关于UIView 的圆顶角并添加边框的主要内容,如果未能解决你的问题,请参考以下文章

IOS / Objective-C:矩形的圆顶角不擦除边框

在 UIView 外部(而不是内部)添加边框

为添加边框的 UIView 创建子类的步骤是啥? [复制]

Objective-c:如何使用自动布局向 UIView 添加边框 [关闭]

如何同时向 UIView 添加顶角、顶边框和顶阴影

UIView边框覆盖子视图?