带虚线的圆圈 uiview

Sha*_*Ali 5 uiview ios swift

我正在尝试用虚线做一个圆圈。我能够在矩形中制作线条,但我不知道如何在圆形中制作这些线条。这是我得到的答案,但它在 Objective-C 中:UIView Draw Circle with Dotted Line Border

这是我的代码,它用虚线制作了一个矩形。

func addDashedBorder() {
    let color = UIColor.red.cgColor

    let shapeLayer:CAShapeLayer = CAShapeLayer()
    let frameSize = self.frame.size
    let shapeRect = CGRect(x: 0, y: 0, width: frameSize.width, height: frameSize.height)

    shapeLayer.bounds = shapeRect
    shapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height/2)
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.strokeColor = color
    shapeLayer.lineWidth = 2
    shapeLayer.lineJoin = CAShapeLayerLineJoin.round
    shapeLayer.lineDashPattern = [6,3]
    shapeLayer.path = UIBezierPath(roundedRect: shapeRect, cornerRadius: 5).cgPath

    self.layer.addSublayer(shapeLayer)
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 7

当然,您可以UIBezierPath使用选定的虚线图案渲染圆形:

class DashedCircleView: UIView {
    private var shapeLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.strokeColor = UIColor.red.cgColor
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.lineWidth = 10
        shapeLayer.lineCap = .round
        shapeLayer.lineDashPattern = [20, 60]
        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 DashedCircleView {
    func configure() {
        layer.addSublayer(shapeLayer)
    }

    func updatePath() {
        let rect = bounds.insetBy(dx: shapeLayer.lineWidth / 2, dy: shapeLayer.lineWidth / 2)
        let radius = min(rect.width, rect.height) / 2
        let center = CGPoint(x: rect.midX, y: rect.midY)
        let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: .pi * 2, clockwise: true)
        shapeLayer.path = path.cgPath
    }
}
Run Code Online (Sandbox Code Playgroud)

这产生:

在此处输入图片说明

这种方法的问题是很难让虚线图案对齐(注意“3 点钟”位置的笨拙虚线)。您可以通过确保 的两个值lineDashPattern加起来等于某个数字来解决这个问题,该数字可以均匀地划分为圆的周长(例如 2? × 半径):

let circumference: CGFloat = 2 * .pi * radius
let count = 30
let relativeDashLength: CGFloat = 0.25
let dashLength = circumference / CGFloat(count)
shapeLayer.lineDashPattern = [dashLength * relativeDashLength, dashLength * (1 - relativeDashLength)] as [NSNumber]
Run Code Online (Sandbox Code Playgroud)

或者,lineDashPattern您可以不使用,而是保留实心笔划,并将path本身作为一系列小弧线。这样我就可以实现所需的虚线效果,但要确保count在我们从 0 旋转到 2 时将其均匀地分成小弧线?:

class DashedCircleView: UIView {
    private var shapeLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.strokeColor = UIColor.red.cgColor
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.lineWidth = 10
        shapeLayer.lineCap = .round
        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 DashedCircleView {
    func configure() {
        layer.addSublayer(shapeLayer)
    }

    func updatePath() {
        let rect = bounds.insetBy(dx: shapeLayer.lineWidth / 2, dy: shapeLayer.lineWidth / 2)
        let radius = min(rect.width, rect.height) / 2
        let center = CGPoint(x: rect.midX, y: rect.midY)

        let path = UIBezierPath()
        let count = 30
        let relativeDashLength: CGFloat = 0.25 // a value between 0 and 1
        let increment: CGFloat = .pi * 2 / CGFloat(count)

        for i in 0 ..< count {
            let startAngle = increment * CGFloat(i)
            let endAngle = startAngle + relativeDashLength * increment
            path.move(to: CGPoint(x: center.x + radius * cos(startAngle), 
                                  y: center.y + radius * sin(startAngle)))
            path.addArc(withCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
        } 
        shapeLayer.path = path.cgPath
    }
}
Run Code Online (Sandbox Code Playgroud)

这产生:

在此处输入图片说明