如何为UIView的左上角和右上角设置cornerRadius?

548

有没有一种方法可以仅为UIView的左上角和右上角设置cornerRadius

我尝试了以下方法,但最终导致无法看到视图。

UIView *view = [[UIView alloc] initWithFrame:frame];

CALayer *layer = [CALayer layer];
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight) cornerRadii:CGSizeMake(3.0, 3.0)];
layer.shadowPath = shadowPath.CGPath;
view.layer.mask = layer;

9
在您的编辑后,有三个需要修正的地方:(1)圆角路径应基于 view.bounds,而不是 frame;(2)图层应该是一个 CAShapeLayer,而不是 CALayer;(3)设置图层的 path,而不是 shadowPath - Kurt Revis
1
可能是这个问题的重复:question & answer - Stuart
使用Bezier曲线算法,在CGPath上创建曲线。我相信它是CoreGraphics的一部分。如果不是,http://en.wikipedia.org/wiki/Bézier_curve有一些很好的定义和动画。 - Nate Symer
https://iosdevcenters.blogspot.com/2018/02/how-to-set-roundcorner-radius-on-view.html - Bhadresh
请查看我的答案:https://dev59.com/I10b5IYBdhLWcg3wGN0s#50396485 - wcarhart
显示剩余2条评论
31个回答

29

iOS 11,Swift 4
您可以尝试此代码:

if #available(iOS 11.0, *) {
   element.clipsToBounds = true
   element.layer.cornerRadius = CORNER_RADIUS
   element.layer.maskedCorners = [.layerMaxXMaxYCorner]
} else {
   // Fallback on earlier versions
}

你可以在表格视图中使用这个。


2
那就是今天编程的正确答案。再见遮罩层。 - Alen Liang
1
这一定是最好的答案! - fujianjin6471

18

我在Swift中为UIView和UITextFiels设置特定圆角的解决方案是使用实际的UIView或UITextFields的

.layer.cornerRadius

layer.maskedCorners

示例:

fileprivate func inputTextFieldStyle() {
        inputTextField.layer.masksToBounds = true
        inputTextField.layer.borderWidth = 1
        inputTextField.layer.cornerRadius = 25
        inputTextField.layer.maskedCorners = [.layerMaxXMaxYCorner,.layerMaxXMinYCorner]
        inputTextField.layer.borderColor = UIColor.white.cgColor
    }

通过使用

.layerMaxXMaxYCorner

.layerMaxXMinYCorner

,我可以指定UITextField的右上角和右下角进行圆角处理。

您可以在此处查看结果:

在此输入图片描述


完美用于边框和特定角落的组合。 - nomnom
完美解决方案 - Manish Singh

17

Emma: .TopRight.BottomRight可能不适用于您,因为在计算最终的view bounds之前调用了view.roundCorners。请注意,Bezier Path是根据其被调用时的视图边界派生出来的。例如,如果自动布局会缩小视图,则右侧的圆角可能在视图外部。 尝试在viewDidLayoutSubviews中调用它,此时视图的边界是最终的。


谢谢。对我来说,解决问题的方法是将调用“Arbitur”提供的实现从viewDidLoad和viewWillAppear移动到viewDidAppear中。我可以这样做,因为我的控件最初设置为隐藏状态。 - Matti
你是对的。这会导致自动布局出现问题,你做得很好。 - Ashish Kakkad

17

试试这段代码:

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

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.view.bounds;
maskLayer.path  = maskPath.CGPath;

view.layer.mask = maskLayer;

12

简单的扩展

extension UIView {
    func roundCorners(corners: UIRectCorner, radius: CGFloat) {
        if #available(iOS 11, *) {
            self.clipsToBounds = true
            self.layer.cornerRadius = radius
            var masked = CACornerMask()
            if corners.contains(.topLeft) { masked.insert(.layerMinXMinYCorner) }
            if corners.contains(.topRight) { masked.insert(.layerMaxXMinYCorner) }
            if corners.contains(.bottomLeft) { masked.insert(.layerMinXMaxYCorner) }
            if corners.contains(.bottomRight) { masked.insert(.layerMaxXMaxYCorner) }
            self.layer.maskedCorners = masked
        }
        else {
            let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            layer.mask = mask
        }
    }
}

用法:

view.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 12)

11

Swift 4

extension UIView {

    func roundTop(radius:CGFloat = 5){
        self.clipsToBounds = true
        self.layer.cornerRadius = radius
        if #available(iOS 11.0, *) {
            self.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
        } else {
            // Fallback on earlier versions
        }
    }

    func roundBottom(radius:CGFloat = 5){
        self.clipsToBounds = true
        self.layer.cornerRadius = radius
        if #available(iOS 11.0, *) {
            self.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
        } else {
            // Fallback on earlier versions
        }
    }
}

你在编程中帮了我大忙,我的情况是我必须将表视图的特定单元格圆角化。 - Shakti
根据我的需求,您的回答非常完美。我尝试了所有答案,但没有一个可行,但是你的回答帮助了我,解决了我的问题。 - Nikita Patil

9

使用这个扩展,它会覆盖所有内容。

extension UIView {

   func roundTopCorners(radius: CGFloat = 10) {
    
       self.clipsToBounds = true
       self.layer.cornerRadius = radius
       if #available(iOS 11.0, *) {
           self.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
       } else {
           self.roundCorners(corners: [.topLeft, .topRight], radius: radius)
       }
   }

   func roundBottomCorners(radius: CGFloat = 10) {
    
       self.clipsToBounds = true
       self.layer.cornerRadius = radius
       if #available(iOS 11.0, *) {
           self.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
       } else {
           self.roundCorners(corners: [.bottomLeft, .bottomRight], radius: radius)
       }
   }

   private func roundCorners(corners: UIRectCorner, radius: CGFloat) {
    
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        layer.mask = mask
    }
}

然后像这样使用:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
            
    self.yourView.roundTopCorners()
}

注意:我建议不要将这段代码放在 viewDidLayoutSubviews() 中,因为每当视图更新时,它都会被调用。因此,请使用 viewDidAppear(),它会像魔术一样运行。

@SourabhSharma 很高兴能帮到你 :) - Vipul Kumar

7

以下是最佳方式Swift 5

import UIKit

extension UIView {

func roundCorners(radius: CGFloat = 10, corners: UIRectCorner = .allCorners) {
        self.clipsToBounds = true
        self.layer.cornerRadius = radius
        if #available(iOS 11.0, *) {
            var arr: CACornerMask = []
            
            let allCorners: [UIRectCorner] = [.topLeft, .topRight, .bottomLeft, .bottomRight, .allCorners]
            
            for corn in allCorners {
                if(corners.contains(corn)){
                    switch corn {
                    case .topLeft:
                        arr.insert(.layerMinXMinYCorner)
                    case .topRight:
                        arr.insert(.layerMaxXMinYCorner)
                    case .bottomLeft:
                        arr.insert(.layerMinXMaxYCorner)
                    case .bottomRight:
                        arr.insert(.layerMaxXMaxYCorner)
                    case .allCorners:
                        arr.insert(.layerMinXMinYCorner)
                        arr.insert(.layerMaxXMinYCorner)
                        arr.insert(.layerMinXMaxYCorner)
                        arr.insert(.layerMaxXMaxYCorner)
                    default: break
                    }
                }
            }
            self.layer.maskedCorners = arr
        } else {
            self.roundCornersBezierPath(corners: corners, radius: radius)
        }
    }
    
    private func roundCornersBezierPath(corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        layer.mask = mask
    }
    
}

6
    // Create the path (with only the top-left corner rounded)
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds 
                           byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight) 
                           cornerRadii:CGSizeMake(7.0, 7.0)];

// Create the shape layer and set its path
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = cell.stripBlackImnageView.bounds;
maskLayer.path = maskPath.CGPath; 
// Set the newly created shapelayer as the mask for the image view's layer
view.layer.mask = maskLayer;

6
以编程方式实现此操作的方法是创建一个 UIView 覆盖具有圆角的 UIView 的顶部部分。或者您可以将其隐藏在某个东西下面。

7
这是一个非常丑陋的解决方案:P。 - Arbitur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接