I need to create a rectangle that have just two rounded corners in swift (Objective C code also ok).
At the moment my code is creating two rectangles with
Swift 3 - Useful UIView
extension when you need to round specific corners of some views:
extension UIView {
func round(corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
}
}
then just use it like this:
someView.round(corners: [.topLeft, .topRight], radius: 5)
Here is what you do in Swift 2.0
var maskPath = UIBezierPath(roundedRect: anyView.bounds,
byRoundingCorners: [.BottomLeft, .BottomRight],
cornerRadii: CGSize(width: 10.0, height: 10.0))
In Swift 2.3 you could do so by
let maskPath = UIBezierPath(roundedRect: anyView.bounds,
byRoundingCorners: [.BottomLeft, .BottomRight],
cornerRadii: CGSize(width: 10.0, height: 10.0))
let shape = CAShapeLayer()
shape.path = maskPath.CGPath
view.layer.mask = shape
In Objective-C you could use the UIBezierPath
class method
bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
example implementation-
// set the corner radius to the specified corners of the passed container
- (void)setMaskTo:(UIView*)view byRoundingCorners:(UIRectCorner)corners
{
UIBezierPath *rounded = [UIBezierPath bezierPathWithRoundedRect:view.bounds
byRoundingCorners:corners
cornerRadii:CGSizeMake(10.0, 10.0)];
CAShapeLayer *shape = [[CAShapeLayer alloc] init];
[shape setPath:rounded.CGPath];
view.layer.mask = shape;
}
and call the above method as-
[self setMaskTo:anyView byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight];
Swift 4+, iOS 11+
If you already have a UIView
named myView
referenced as an IBOutlet
, try adding the following two lines in ViewDidLoad()
or wherever it's being loaded:
myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
You can change the array []
to any combination of MinX
, MinY
, MaxX
, and MaxY
to select the desired corners. The above example rounds the bottom two corners.
This is just another approach, can be a bit simpler depending on your design.
iOS 11+ Only | You can check iOS usage stats here
Since the CACornerMask
rawValue is an UInt
you know that a CACornerMask
rawValue is the sum of each CACornerMask.Element
rawValue
More specifically:
layerMinXMinYCorner
) = 1layerMaxXMinYCorner
) = 2layerMinXMaxYCorner
) = 4layerMaxXMaxYCorner
) = 8So for example if you want top left and top right corners you can just type CACornerMask(rawValue: 3)
.
Below a simple extension of an UIView
extension UIView {
enum Corner:Int {
case bottomRight = 0,
topRight,
bottomLeft,
topLeft
}
private func parseCorner(corner: Corner) -> CACornerMask.Element {
let corners: [CACornerMask.Element] = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMinXMinYCorner]
return corners[corner.rawValue]
}
private func createMask(corners: [Corner]) -> UInt {
return corners.reduce(0, { (a, b) -> UInt in
return a + parseCorner(corner: b).rawValue
})
}
func roundCorners(corners: [Corner], amount: CGFloat = 5) {
layer.cornerRadius = amount
let maskedCorners: CACornerMask = CACornerMask(rawValue: createMask(corners: corners))
layer.maskedCorners = maskedCorners
}
}
You can use this like:
let myRect = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
myRect.roundCorners(corners: [.topRight, .topLeft])
extension CACornerMask {
public static var leftBottom : CACornerMask { get { return .layerMinXMaxYCorner}}
public static var rightBottom : CACornerMask { get { return .layerMaxXMaxYCorner}}
public static var leftTop : CACornerMask { get { return .layerMaxXMinYCorner}}
public static var rightTop : CACornerMask { get { return .layerMinXMinYCorner}}
}
extension CALayer {
func roundCorners(_ mask:CACornerMask,corner:CGFloat) {
self.maskedCorners = mask
self.cornerRadius = corner
}
}
self.viewBack.layer.roundCorners([.leftBottom,.rightBottom], corner: 23)