我有这段代码来绘制一个仅一侧为圆角矩形的矩形。
override func draw(_ rect: CGRect) {
// Drawing code
guard let context = UIGraphicsGetCurrentContext() else { return }
let lineWidth = CGFloat(4)
let pathRect = CGRect(x: 0, y: 0, width: rect.width, height: rect.height)
let path = UIBezierPath(roundedRect: pathRect.inset(by: UIEdgeInsets(top: lineWidth, left: lineWidth, bottom: lineWidth, right: 0)), byRoundingCorners: [.topLeft, .bottomLeft], cornerRadii: CGSize(width: 7, height: 7))
context.setFillColor(UIColor.black.cgColor)
path.fill()
context.setLineWidth(lineWidth)
}
我想在除右边缘之外的所有边缘上用红色描边(右边缘上没有描边)。我该怎么做?
最佳答案
您必须创建自己的路径。
一些观察结果:
不要使用
rect
参数。矩形是此时要求绘制的内容,它可能不是整个 View 。在确定总体路径应该是什么时,请使用边界。我可能会插入路径,以便笔划保持在 View 的边界内。
如果您还希望能够看到它在 IB 中呈现,您可以将其设为
@IBDesignable
。您实际上并不需要
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(_:)
可能会更有效。例如,他们可能优化了渲染以处理部分 View 更新等。
可能如下所示:
@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
}
}
关于ios - UIBezierPath 部分描边,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56224618/