How can I make a quadrant (quarter-circle) like the one below, using Auto-Layout in Swift? I understand that UIBezierPath
is required but I can't seem to get it to work.
CodePudding user response:
Quick, simple example:
class QuarterCircleView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
// only add the shape layer once
if layer.sublayers == nil {
let lay = CAShapeLayer()
lay.fillColor = UIColor.blue.cgColor
layer.addSublayer(lay)
}
if let lay = layer.sublayers?.first as? CAShapeLayer {
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let bez = UIBezierPath()
bez.move(to: center)
bez.addArc(withCenter: center, radius: bounds.width * 0.5, startAngle: .pi, endAngle: .pi * 1.5, clockwise: true)
bez.close()
lay.path = bez.cgPath
}
}
}
Note: you really should show what you've tried when posting a question. Search for CAShapeLayer
and read some tutorials.
CodePudding user response:
Modifying DonMag's answer slightly to make the view's layer a CAShapeLayer so we don't have to worry about adding a sublayer or checking for an existing sublayer:
class QuarterCircleView: UIView {
// By adding this static var, we can change the type of our view's layer (in this case, to a CAShapeLayer)
static override var layerClass: AnyClass {
return CAShapeLayer.self
}
// This lets us use the view's layer as a CAShapeLayer without type casting.
var shapeLayer: CAShapeLayer {
return self.layer as! CAShapeLayer
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
shapeLayer.fillColor = UIColor.blue.cgColor
}
// Every time we update our subviews, also regenerate our shape layer's path.
override func layoutSubviews() {
super.layoutSubviews()
// We want a quarter-circle centered on the lower right of teh view.
let center = CGPoint(x:bounds.maxX, y:bounds.maxY)
let bez = UIBezierPath()
bez.move(to: center)
// As long as our view is square, the below isn't needed, but let's be sure.
let radius = min(bounds.width, bounds.height)
bez.addArc(withCenter: center, radius: radius, startAngle: .pi, endAngle: .pi * 1.5, clockwise: true)
bez.close()
shapeLayer.path = bez.cgPath
}
}
Mine looks like this: (With a 1-pixel border around the view so you can see its bounds: