ios - UIBezierPath 部分描边

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

我想在除右边缘之外的所有边缘上用红色描边(右边缘上没有描边)。我该怎么做?

最佳答案

您必须创建自己的路径。

一些观察结果:

  • 不要使用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()
    }
}

结果是:

enter image description here


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

相关文章:

ios - 将 tableview 添加到 scrollview 并让 scrollview 在单元格添加到 tableview 时保持高度增长

ios - Swift - 以编程方式创建 View 问题,无法找到存储的属性

arrays - Swift 3 多维数组,适用于 Swift 2.2 及更早版本

ios - ARKit/SpriteKit - 将 pixelBufferAttributes 设置为 SKVideoNode 或以另一种方式在视频中制作透明像素(色度键效果)

swift - “NSInvalidArgumentException”关闭

swift - 如何在 Swift 中使 NSAttributedString 的特定片段成为特定颜色

ios - UITableView 和分段 Controller 在 IOS 11 的导航栏下移动

ios - 无法在 View Controller 上为 Table View 和 Segmented Control 添加约束

ios - 如何继承 UICollectionViewLayoutAttributes

iOS放大 View 不显示