Search code examples
ioscocoa-touchuiviewcornerradius

How to set cornerRadius for only top-left and top-right corner of a UIView?


Is there a way to set cornerRadius for only top-left and top-right corner of a UIView?

I tried the following, but it end up not seeing the view anymore.

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;

Solution

  • Pay attention to the fact that if you have layout constraints attached to it, you must refresh this as follows in your UIView subclass:

    override func layoutSubviews() {
        super.layoutSubviews()
        roundCorners(corners: [.topLeft, .topRight], radius: 3.0)
    }
    

    If you don't do that it won't show up.


    And to round corners, use the extension:

    extension UIView {
       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
        }
    }
    


    Additional view controller case: Whether you can't or wouldn't want to subclass a view, you can still round a view. Do it from its view controller by overriding the viewWillLayoutSubviews() function, as follows:

    class MyVC: UIViewController {
        /// The view to round the top-left and top-right hand corners
        let theView: UIView = {
            let v = UIView(frame: CGRect(x: 10, y: 10, width: 200, height: 200))
            v.backgroundColor = .red
            return v
        }()
        
        override func loadView() {
            super.loadView()
            view.addSubview(theView)
        }
        
        override func viewWillLayoutSubviews() {
            super.viewWillLayoutSubviews()
    
            // Call the roundCorners() func right there.
            theView.roundCorners(corners: [.topLeft, .topRight], radius: 30)
        }
    }