UIBezierPath部分笔画

时间:2019-05-20 16:12:07

标签: ios swift uikit uibezierpath cgcontext

我有这段代码来绘制一个仅在一侧修圆的矩形。

this one

  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)
}

我要在除右边缘以外的所有位置上用红色描边(在右边缘上无描边)。我该怎么办?

1 个答案:

答案 0 :(得分:1)

您必须创建自己的路径。

一些观察结果:

  • 请勿使用rect参数。 rect是此时要求绘制的内容,可能不是整个视图。确定总体路径应使用bounds

  • 我可能会插入路径,以使笔划保持在视图范围之内。

  • 如果您还希望能够看到它在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()
    }
}

结果是:

enter image description here


从理论上讲,使用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
    }
}