What's currently the "correct" way to set a UIView's corner radius?

ios, swift, uiview

Solution

Note that I don't know what's currently the “correct” way to set a UIView's corner radius.

What I prefer to do is to use Interface Builder as much as possible without having extra code which this approach shows and is reliable to my experience.

From iOS 11 upwards

you can use user-defined runtime attributes in the `Identity inspector` of the `Interface Builder` by setting the following properties:

layer.cornerRadius
layer.maskedCorners
layer.masksToBounds

According to the documentation of the CACornerMask you can see that the `maskedCorners` property is in fact a `NSUInteger` data type and you're allowed to set the following values:

kCALayerMinXMinYCorner = 1U << 0
kCALayerMaxXMinYCorner = 1U << 1
kCALayerMinXMaxYCorner = 1U << 2
kCALayerMaxXMaxYCorner = 1U << 3

Since you're allowed to `bitwise OR` those masks together you only have to "calculate" the resulting integer of that bitwise OR of what you actually need.

Therefore set the following number (integer) values for the `maskedCorners` property to get rounded corners:

 0 = no corner is being rounded
 1 = top left corner rounded only
 2 = top right corner rounded only
 3 = top left and top right corners rounded only
 4 = bottom left corner rounded only
 5 = top left and bottom left corners rounded only
 6 = top right and bottom left corners rounded only
 7 = top left, top right and bottom left corners rounded only
 8 = bottom right corner rounded only
 9 = top left and bottom right corners rounded only
10 = top right and bottom right corners rounded only
11 = top left, top right and bottom right corners rounded only
12 = bottom left and bottom right corners rounded only
13 = top left, bottom left and bottom right corners rounded only
14 = top right, bottom left and bottom right corners rounded only
15 = all corners rounded

Example: If you want to set the corner radius for the top-left and the top-right corners of a UIView you would use those attributes:

Problem

Setting a `UIView`'s corner radius can be done the following ways: Set the `layer`'s `cornerRadius` property: ``` view.layer.cornerRadius = 5; view.layer.masksToBounds = true; ``` Apply a mask: ``` func roundCorners(corners:UIRectCorner, radius: CGFloat) { 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 } ``` Override `draw(_:)`: ``` func draw(_ rect: CGRect) { // Size of rounded rectangle let rectWidth = rect.width let rectHeight = rect.height // Find center of actual frame to set rectangle in middle let xf: CGFloat = (self.frame.width - rectWidth) / 2 let yf: CGFloat = (self.frame.height - rectHeight) / 2 let ctx = UIGraphicsGetCurrentContext()! ctx.saveGState() let rect = CGRect(x: xf, y: yf, width: rectWidth, height: rectHeight) let clipPath = UIBezierPath(roundedRect: rect, cornerRadius: rectCornerRadius).cgPath ctx.addPath(clipPath) ctx.setFillColor(rectBgColor.cgColor) ctx.closePath() ctx.fillPath() ctx.restoreGState() } ``` Which of these is generally considered to be the "correct" way of implementing rounded corners on a `UIView`, accounting for the following criteria: - configuration (some corners may be rounded while others are not) - animation (can you animate the `cornerRadius` changing) - flexibility (does it break third party libraries or masks you have already applied) - readability (how concise/reusable is the solution) - speed (does it negatively impact performance)

Original source

Related problems