Round Top Corners of a UIView in Swift

10.4k Views Asked by At

I am trying to round top corners using below code

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

use myView.roundCorners(corners:[.topLeft, .topRight], radius: radius)

But it's rounding one side of the view:
enter image description here

this is in a tableView sectionHeader if I scroll down then up it rounded using same code: enter image description here

And also top discount view corners are rounded using same function.

thank's for help.

Update if I fix the width on the view then it works fine.

3

There are 3 best solutions below

0
On BEST ANSWER

Solved this with the help of @Paolo and below is the working code.

Swift 3.2

extension UIView {

    func roundCorners(corners:UIRectCorner, radius: CGFloat) {

        DispatchQueue.main.async {
            let path = UIBezierPath(roundedRect: self.bounds,
                                    byRoundingCorners: corners,
                                    cornerRadii: CGSize(width: radius, height: radius))
            let maskLayer = CAShapeLayer()
            maskLayer.frame = self.bounds
            maskLayer.path = path.cgPath
            self.layer.mask = maskLayer
        }
    }
}

for calling this function use below line and mention which corners you want to round

self.myView.roundCorners(corners: [.topLeft, .topRight, .bottomLeft, .bottomRight], radius: 8.0)
0
On

iOS 11 introduced maskedCorners which results in smoother and better quality results. You can still use the UIRectCorner in the function call and have it translated to CACornerMask:

Swift 5:

extension UIView {

    func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
        if #available(iOS 11.0, *) {
            clipsToBounds = true
            layer.cornerRadius = radius
            layer.maskedCorners = CACornerMask(rawValue: corners.rawValue)
        } else {
            let path = UIBezierPath(
                roundedRect: bounds, 
                byRoundingCorners: corners, 
                cornerRadii: CGSize(width: radius, height: radius)
            )
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            layer.mask = mask
        }
    }
}
0
On

also can done as

extension UIView {

func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
    if #available(iOS 11.0, *) {
        clipsToBounds = true
        layer.cornerRadius = radius
        corners.forEach { corner in 
         layer.maskedCorners = CACornerMask(rawValue: corner.rawValue)
        }
    } else {
        corners.forEach { corner in
            let path = UIBezierPath(
                roundedRect: bounds,
                byRoundingCorners: corner,
                cornerRadii: CGSize(width: radius, height: radius)
            )
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            layer.mask = mask
        }
    }
}

}

and can be used as

yourView.roundCorners(.topLeft, .topRight, radius: 8)