Вам придется создать свой собственный путь.
Пара наблюдений:
Не используйте параметр rect
. rect
- это то, что просят нарисовать в данный момент времени, что может быть не полностью. Используйте bounds
, чтобы выяснить, каким должен быть общий путь.
Я мог бы вставить путь так, чтобы штрих оставался в границах вида.
Вы можете сделать это @IBDesignable
, если хотите, чтобы вы также могли видеть его в IB.
Вам действительно не нужно UIGraphicsGetCurrentContext()
. Методы UIKit
fill()
, stroke()
, setFill()
и setStroke()
автоматически используют текущий контекст.
Таким образом:
@IBDesignable
class OpenRightView: UIView {
@IBInspectable var lineWidth: CGFloat = 4 { didSet { setNeedsDisplay() } }
@IBInspectable var radius: CGFloat = 7 { didSet { setNeedsDisplay() } }
@IBInspectable var fillColor: UIColor = .black { didSet { setNeedsDisplay() } }
@IBInspectable var strokeColor: UIColor = .red { didSet { setNeedsDisplay() } }
override func draw(_ rect: CGRect) {
let pathRect = bounds.inset(by: .init(top: lineWidth / 2, left: lineWidth / 2, bottom: lineWidth / 2, right: 0))
let path = UIBezierPath()
path.lineWidth = lineWidth
path.move(to: CGPoint(x: pathRect.maxX, y: pathRect.minY))
path.addLine(to: CGPoint(x: pathRect.minX + radius, y: pathRect.minY))
path.addQuadCurve(to: CGPoint(x: pathRect.minX, y: pathRect.minY + radius), controlPoint: pathRect.origin)
path.addLine(to: CGPoint(x: pathRect.minX, y: pathRect.maxY - radius))
path.addQuadCurve(to: CGPoint(x: pathRect.minX + radius, y: pathRect.maxY), controlPoint: CGPoint(x: pathRect.minX, y: pathRect.maxY))
path.addLine(to: CGPoint(x: pathRect.maxX, y: pathRect.maxY))
fillColor.setFill()
path.fill()
strokeColor.setStroke()
path.stroke()
}
}
Что дает:
Теоретически, может быть более эффективно использовать CAShapeLayer
и позволить Apple позаботиться о draw(_:)
для нас. Например, они могли оптимизировать рендеринг для обработки частичных обновлений представлений и т. Д.
Это может выглядеть следующим образом:
@IBDesignable
class OpenRightView: UIView {
@IBInspectable var lineWidth: CGFloat = 4 { didSet { updatePath() } }
@IBInspectable var radius: CGFloat = 7 { didSet { updatePath() } }
@IBInspectable var fillColor: UIColor = .black { didSet { shapeLayer.fillColor = fillColor.cgColor } }
@IBInspectable var strokeColor: UIColor = .red { didSet { shapeLayer.strokeColor = strokeColor.cgColor } }
lazy var shapeLayer: CAShapeLayer = {
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = fillColor.cgColor
shapeLayer.strokeColor = strokeColor.cgColor
shapeLayer.lineWidth = lineWidth
return shapeLayer
}()
override init(frame: CGRect = .zero) {
super.init(frame: frame)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
override func layoutSubviews() {
super.layoutSubviews()
updatePath()
}
}
private extension OpenRightView {
func configure() {
layer.addSublayer(shapeLayer)
}
func updatePath() {
let pathRect = bounds.inset(by: .init(top: lineWidth / 2, left: lineWidth / 2, bottom: lineWidth / 2, right: 0))
let path = UIBezierPath()
path.move(to: CGPoint(x: pathRect.maxX, y: pathRect.minY))
path.addLine(to: CGPoint(x: pathRect.minX + radius, y: pathRect.minY))
path.addQuadCurve(to: CGPoint(x: pathRect.minX, y: pathRect.minY + radius), controlPoint: pathRect.origin)
path.addLine(to: CGPoint(x: pathRect.minX, y: pathRect.maxY - radius))
path.addQuadCurve(to: CGPoint(x: pathRect.minX + radius, y: pathRect.maxY), controlPoint: CGPoint(x: pathRect.minX, y: pathRect.maxY))
path.addLine(to: CGPoint(x: pathRect.maxX, y: pathRect.maxY))
shapeLayer.path = path.cgPath
shapeLayer.lineWidth = lineWidth
}
}