iOS-Swift-圆环进度条

截屏2022-03-07 上午10.16.41.png

用 CAShapeLayer 和 UIBezierPath 贝塞尔曲线实现,每次进度变化时,重新初始化一个 CAShapeLayer 添加到当前 UIView 上。


import Foundation
import UIKit

class CircleProgressView: UIView {
    // 灰色静态圆环
    var staticLayer: CAShapeLayer!
    // 进度可变圆环
    var arcLayer: CAShapeLayer!
    
    // 为了显示更精细,进度范围设置为 0 ~ 1000
    var progress = 0

    override init(frame: CGRect) {
        super.init(frame: frame)

    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setProgress(_ progress: Int) {
        self.progress = progress
        setNeedsDisplay()
    }
    
    override func draw(_ rect: CGRect) {
        if staticLayer == nil {
            staticLayer = createLayer(1000, .gray)
        }
        self.layer.addSublayer(staticLayer)
        if arcLayer != nil {
            arcLayer.removeFromSuperlayer()
        }
        arcLayer = createLayer(self.progress, .red)
        self.layer.addSublayer(arcLayer)
    }
    
    private func createLayer(_ progress: Int, _ color: UIColor) -> CAShapeLayer {
        let endAngle = -CGFloat.pi / 2 + (CGFloat.pi * 2) * CGFloat(progress) / 1000
        let layer = CAShapeLayer()
        layer.lineWidth = 1.5
        layer.strokeColor = color.cgColor
        layer.fillColor = UIColor.clear.cgColor
        let radius = self.bounds.width / 2 - layer.lineWidth
        let path = UIBezierPath.init(arcCenter: CGPoint(x: bounds.width / 2, y: bounds.height / 2), radius: radius, startAngle: -CGFloat.pi / 2, endAngle: endAngle, clockwise: true)
        layer.path = path.cgPath
        return layer
    }

}

posted @ 2022-07-18 17:41  rome753  阅读(483)  评论(0编辑  收藏  举报