Skip to content

Instantly share code, notes, and snippets.

@renssies
Created July 6, 2020 16:15
Show Gist options
  • Save renssies/5c430a2790d7dc63f396f6a51e03d1fa to your computer and use it in GitHub Desktop.
Save renssies/5c430a2790d7dc63f396f6a51e03d1fa to your computer and use it in GitHub Desktop.
Create a rounded UIBezierPath with a different corner radius per corner
extension UIBezierPath {
/// Defines a corner of a rounded rectangle path.
public enum RoundedRectCorner {
case topLeft
case topRight
case bottomLeft
case bottomRight
case all
}
/// Creates a rounded rectangle with the given corners.
/// This allows the creation of a rectangle with a different corner radius for one of more corners.
///
/// Be warned that this method does not clamp the corner radius for specific corners. It is possible to end up with an invalid or incorrect path while doing this.
///
/// **Example**
///
/// In order to change 1 corner from the rest, simply supply `.all` and the corner you want to change to `corners:`.
/// `[.all: 26, .bottomRight: 9]`
///
/// - Parameters:
/// - rect: The rectangle that defines the basic shape of the path
/// - corners: The corners to adjust the corner radius for. The specific corner will always take priority over the `all` option.
convenience init(roundedRect rect: CGRect, corners: [RoundedRectCorner: CGFloat]) {
self.init()
let allCorners = min(corners[.all] ?? 0, rect.width / 2, rect.height / 2)
let topLeft = corners[.topLeft] ?? allCorners
let topRight = corners[.topRight] ?? allCorners
let bottomLeft = corners[.bottomLeft] ?? allCorners
let bottomRight = corners[.bottomRight] ?? allCorners
let path = self
path.move(to: CGPoint(x: 0 + topLeft, y: 0)); // Move to top left but inset with radius
path.addLine(to: CGPoint(x: rect.width - topRight, y: 0)) // Add line at the top from left to right
path.addArc(withCenter: CGPoint(x: rect.width - topRight, y: topRight), radius: topRight, startAngle: 3 * .pi / 2, endAngle: 0, clockwise: true) // Add top right rounded corner
path.addLine(to: CGPoint(x: rect.width, y: rect.height - bottomRight)) // Add line from top to bottom on right side
path.addArc(withCenter: CGPoint(x: rect.height - bottomRight, y: rect.width - bottomRight), radius: bottomRight, startAngle: 0, endAngle: .pi / 2, clockwise: true) // Add bottom right rounded corner
path.addLine(to: CGPoint(x: bottomLeft, y: rect.height)) // Add line from bottom right to bottom left
path.addArc(withCenter: CGPoint(x: bottomLeft, y: rect.height - bottomLeft), radius: bottomLeft, startAngle: .pi / 2, endAngle: .pi, clockwise: true) // Add bottom left rounded corner
path.addLine(to: CGPoint(x: 0, y: topLeft)) // Add line from bottom to top on left side
path.addArc(withCenter: CGPoint(x: topLeft, y: topLeft), radius: topLeft, startAngle: .pi, endAngle: 3 * .pi / 2, clockwise: true) // Add top left rounded corner
path.close() // Complete the path
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment