【问题标题】:UIBezierPath partially strokeUIBezierPath 部分描边
【发布时间】:2019-05-20 16:12:07
【问题描述】:

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

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

我想在除了右边缘以外的所有地方都用红色描边(右边缘没有描边)。我该怎么做?

【问题讨论】:

    标签: ios swift uikit uibezierpath cgcontext


    【解决方案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()
        }
    }
    

    产生:


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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-25
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多