边框仅在 UIBezierPath() 的角落处错误 space in lineDashPattern

Border only in corners with UIBezierPath() wrong space in lineDashPattern

我正在尝试使用 lineDashPattern 创建一个仅在角落(qrCode 样式)带有边框的视图,但线条之间的 space 似乎与我定义的模式不匹配。这是我的游乐场:

override func loadView() {
    let view = UIView()
    view.backgroundColor = .white
    let myView = UIView(frame: CGRect(x: 50, y: 50, width: 200, height: 200))
    myView.backgroundColor = .black
    let borderLayer = CAShapeLayer()
    let d = (myView.bounds.width / 2) as NSNumber
    borderLayer.strokeColor = UIColor.blue.cgColor
    borderLayer.lineDashPattern = [d]
    borderLayer.frame = myView.bounds
    borderLayer.fillColor = nil
    borderLayer.lineWidth = 10
    borderLayer.strokeStart = 0.1
    //borderLayer.lineDashPhase = -80
    borderLayer.path = UIBezierPath(roundedRect: myView.bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: 30, height: 30)).cgPath
    borderLayer.lineCap = CAShapeLayerLineCap.round
    myView.layer.addSublayer(borderLayer)
    view.addSubview(myView)
    self.view = view
}

我正在尝试使用 lineDashPhase 和 strokeStart 属性调整线条的开头,但似乎不起作用。有人可以帮助我吗?

有趣的想法 - 在圆角矩形上使用长破折号...但我不相信你会得到你想要的结果。

您可能想像这样绘制 4 个角:

您的路径开头为:

move to: A
line to: B
arc with center: C.x B.y and clockwise from 9 o'clock to 12 o'clock 
line to: D

然后更新你的点,画出 top-right / bottom-right / bottom-left 个角。

这是一个例子class:

class BracketView: UIView {
    var radius: CGFloat = 30
    var lineLength: CGFloat = 30
    var lineWidth: CGFloat = 10
    var lineColor: UIColor = .blue
    
    var shapeLayer: CAShapeLayer!
    
    override class var layerClass: AnyClass {
        return CAShapeLayer.self
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        shapeLayer = self.layer as? CAShapeLayer
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.lineCap = .round
    }
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // set these properties here, so we can change them if desired
        shapeLayer.strokeColor = lineColor.cgColor
        shapeLayer.lineWidth = lineWidth
        
        let pth = UIBezierPath()
        
        var ptA: CGPoint = .zero
        var ptB: CGPoint = .zero
        var ptC: CGPoint = .zero
        var ptD: CGPoint = .zero
        var arcCenter: CGPoint = .zero
        var startAngle: CGFloat = 0
        
        // top-left corner
        
        startAngle = .pi    // 9 o'clock
        
        ptA.x = bounds.minX
        ptA.y = bounds.minY + radius + lineLength
        
        ptB.x = bounds.minX
        ptB.y = bounds.minY + radius
        
        ptC.x = bounds.minX + radius
        ptC.y = bounds.minY
        
        ptD.x = bounds.minX + radius + lineLength
        ptD.y = bounds.minY

        arcCenter.x = ptC.x
        arcCenter.y = ptB.y
        
        pth.move(to: ptA)
        pth.addLine(to: ptB)
        pth.addArc(withCenter: arcCenter, radius: radius, startAngle: startAngle, endAngle: startAngle + .pi * 0.5, clockwise: true)
        pth.addLine(to: ptD)
        
        // top-right corner
        
        startAngle += (.pi * 0.5)   // 12 o'clock
        
        ptA.x = bounds.maxX - (radius + lineLength)
        ptA.y = bounds.minY
        
        ptB.x = bounds.maxX - radius
        ptB.y = bounds.minY
        
        ptC.x = bounds.maxX
        ptC.y = bounds.minY + radius
        
        ptD.x = bounds.maxX
        ptD.y = bounds.minY + radius + lineLength
        
        arcCenter.x = ptB.x
        arcCenter.y = ptC.y
        
        pth.move(to: ptA)
        pth.addLine(to: ptB)
        pth.addArc(withCenter: arcCenter, radius: radius, startAngle: startAngle, endAngle: startAngle + .pi * 0.5, clockwise: true)
        pth.addLine(to: ptD)
        
        // bottom-right corner
        
        startAngle += (.pi * 0.5)   // 3 o'clock
        
        ptA.x = bounds.maxX
        ptA.y = bounds.maxY - (radius + lineLength)
        
        ptB.x = bounds.maxX
        ptB.y = bounds.maxY - radius
        
        ptC.x = bounds.maxX - radius
        ptC.y = bounds.maxY
        
        ptD.x = bounds.maxX - (radius + lineLength)
        ptD.y = bounds.maxY
        
        arcCenter.x = ptC.x
        arcCenter.y = ptB.y
        pth.move(to: ptA)
        pth.addLine(to: ptB)
        pth.addArc(withCenter: arcCenter, radius: radius, startAngle: startAngle, endAngle: startAngle + .pi * 0.5, clockwise: true)
        
        pth.addLine(to: ptD)
        
        // bottom-left corner
        
        startAngle += (.pi * 0.5)   // 6 o'clock
        
        ptA.x = bounds.minX + radius + lineLength
        ptA.y = bounds.maxY
        
        ptB.x = bounds.minX + radius
        ptB.y = bounds.maxY
        
        ptC.x = bounds.minX
        ptC.y = bounds.maxY - radius
        
        ptD.x = bounds.minX
        ptD.y = bounds.maxY - (radius + lineLength)
        
        arcCenter.x = ptB.x
        arcCenter.y = ptC.y
        
        pth.move(to: ptA)
        pth.addLine(to: ptB)
        pth.addArc(withCenter: arcCenter, radius: radius, startAngle: startAngle, endAngle: startAngle + .pi * 0.5, clockwise: true)
        pth.addLine(to: ptD)
        
        shapeLayer.path = pth.cgPath
    }
    
}

200 x 200 帧的结果,绿色背景: