Last active
February 16, 2019 18:44
-
-
Save robertmryan/14f1d5593fe81b575927229f287f038e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@IBDesignable | |
class CurveIndentedView: UIView { | |
@IBInspectable | |
var radius: CGFloat = 50 { didSet { updatePath() } } | |
private var shapeLayer: CAShapeLayer = { | |
let shapeLayer = CAShapeLayer() | |
shapeLayer.fillColor = UIColor.red.cgColor | |
return shapeLayer | |
}() | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
configure() | |
} | |
required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
configure() | |
} | |
override func layoutSubviews() { | |
super.layoutSubviews() | |
updatePath() | |
} | |
} | |
private extension CurveIndentedView { | |
func configure() { | |
layer.addSublayer(shapeLayer) | |
} | |
func updatePath() { | |
let angle: CGFloat = .pi / 6 // adjust this to whatever you want, between 0 and `.pi / 2`; /6 or /8 are close | |
let controlPointOffset = radius / cos(angle) | |
let endPointOffset = controlPointOffset + sin(angle) * radius | |
let path = UIBezierPath() | |
path.move(to: CGPoint(x: bounds.midX - endPointOffset, y: bounds.minY)) | |
path.addLine(to: CGPoint(x: bounds.minX, y: bounds.minY)) | |
path.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY)) | |
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY)) | |
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY)) | |
path.addLine(to: CGPoint(x: bounds.midX + endPointOffset, y: bounds.minY)) | |
var endPoint = CGPoint(x: bounds.midX + cos(angle) * radius, y: bounds.minY + sin(angle) * radius) | |
var controlPoint = CGPoint(x: bounds.midX + controlPointOffset, y: bounds.minY) | |
path.addQuadCurve(to: endPoint, controlPoint: controlPoint) | |
path.addArc(withCenter: CGPoint(x: bounds.midX, y: bounds.minY), radius: radius, startAngle: angle, endAngle: .pi - angle, clockwise: true) | |
endPoint = CGPoint(x: bounds.midX - endPointOffset, y: bounds.minY) | |
controlPoint = CGPoint(x: bounds.midX - controlPointOffset, y: bounds.minY) | |
path.addQuadCurve(to: endPoint, controlPoint: controlPoint) | |
path.close() | |
shapeLayer.path = path.cgPath | |
} | |
} |
You can then marry that with a rounded corner button:
@IBDesignable
class RoundedCornerButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = min(bounds.width, bounds.height) / 2
clipsToBounds = true
}
}
If you then size and position that appropriately, that yields:
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That yields: