首页 > 解决方案 > 图像周围的 CircleProgressBar

问题描述

我有一个圆形ProgressBar,我尝试将遮罩 ( ).clear的颜色更改为( 下) 但是由于某种原因,当进度加载时,整个遮罩会立即消失,而不是在进度期间消失。谁能帮我识别错误?这是我的演示项目:https ://github.com/tygruletz/CircularProgressBarCAShapeLayerImageViewProgressBar

这是我的 ProgressBar 的代码:

class CircularProgressBar: UIView {

    var currentProgress = 0

    //MARK: awakeFromNib

    override func awakeFromNib() {
        super.awakeFromNib()
        setupView()
        label.text = "\(currentProgress)"
    }


    //MARK: Public

    public var lineWidth:CGFloat = 120 {
        didSet{
            foregroundLayer.lineWidth = lineWidth
            backgroundLayer.lineWidth = lineWidth - (0.20 * lineWidth)
        }
    }

    public var labelSize: CGFloat = 20 {
        didSet {
            label.font = UIFont.systemFont(ofSize: labelSize)
            label.sizeToFit()
            configLabel()
        }
    }

    public var safePercent: Int = 100 {
        didSet{
            setForegroundLayerColorForSafePercent()
        }
    }

    public func setProgress(to progressConstant: Double, withAnimation: Bool) {

        var progress: Double {
            get {
                if progressConstant > 1 { return 1 }
                else if progressConstant < 0 { return 0 }
                else { return progressConstant }
            }
        }

        foregroundLayer.strokeEnd = CGFloat(progress)

        if withAnimation {
            let animation = CABasicAnimation(keyPath: "strokeEnd")
            animation.fromValue = 0
            animation.toValue = progress
            animation.duration = 2
            foregroundLayer.add(animation, forKey: "foregroundAnimation")
        }

        var currentTime:Double = 0
        let timer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { (timer) in
            if currentTime >= 2{
                timer.invalidate()
            } else {
                currentTime += 0.05
                let percent = currentTime/2 * 100

                self.currentProgress = Int(progress * percent)

                self.label.text = "\(self.currentProgress)%"

                self.setForegroundLayerColorForSafePercent()
                self.configLabel()
            }
        }
        timer.fire()
    }

    //MARK: Private
    private var label = UILabel()
    private let foregroundLayer = CAShapeLayer()
    private let backgroundLayer = CAShapeLayer()
    private var radius: CGFloat {
        get{
            if self.frame.width < self.frame.height { return (self.frame.width - lineWidth)/2 }
            else { return (self.frame.height - lineWidth)/2 }
        }
    }

    private var pathCenter: CGPoint{ get{ return self.convert(self.center, from:self.superview) } }
    private func makeBar(){
        self.layer.sublayers = nil
        drawBackgroundLayer()
        drawForegroundLayer()
    }

    private func drawBackgroundLayer(){
        let path = UIBezierPath(arcCenter: pathCenter, radius: self.radius, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
        self.backgroundLayer.path = path.cgPath
        self.backgroundLayer.strokeColor = UIColor(red: CGFloat(105/255.0), green: CGFloat(105/255.0), blue: CGFloat(105/255.0), alpha: 0.85).cgColor
        self.backgroundLayer.lineWidth = lineWidth - (lineWidth * 20/100)
        self.backgroundLayer.fillColor = UIColor.clear.cgColor
        self.layer.addSublayer(backgroundLayer)

    }

    private func drawForegroundLayer(){

        let startAngle = (-CGFloat.pi/2)
        let endAngle = 2 * CGFloat.pi + startAngle

        let path = UIBezierPath(arcCenter: pathCenter, radius: self.radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)

        foregroundLayer.lineCap = CAShapeLayerLineCap.round
        foregroundLayer.path = path.cgPath
        foregroundLayer.lineWidth = lineWidth
        foregroundLayer.fillColor = UIColor.clear.cgColor
        foregroundLayer.strokeColor = UIColor.clear.cgColor
        foregroundLayer.strokeEnd = 0

        self.layer.addSublayer(foregroundLayer)

    }

    private func makeLabel(withText text: String) -> UILabel {
        let label = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
        label.text = text
        label.font = UIFont.systemFont(ofSize: labelSize)
        label.sizeToFit()
        label.center = pathCenter
        return label
    }

    private func configLabel(){
        label.sizeToFit()
        label.center = pathCenter
    }

    private func setForegroundLayerColorForSafePercent(){

        let percent = currentProgress

        if percent > 0 && percent < 100 {

            self.backgroundLayer.strokeColor = UIColor.clear.cgColor
            self.label.textColor = .orange

        }
        else {
            self.backgroundLayer.strokeColor = UIColor(red: CGFloat(105/255.0), green: CGFloat(105/255.0), blue: CGFloat(105/255.0), alpha: 0.85).cgColor
        }
    }

    private func setupView() {
        makeBar()
        self.addSubview(label)
    }

    //Layout Sublayers
    private var layoutDone = false
    override func layoutSublayers(of layer: CALayer) {
        if !layoutDone {
            let tempText = label.text
            setupView()
            label.text = tempText
            layoutDone = true
        }
    }
}

这里我调用 ViewController 中的类:

class ViewController: UIViewController {

    //MARK: IBOutlets
    @IBOutlet weak var progressBar: CircularProgressBar!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))
    }

    @objc func handleTap() {
        progressBar.labelSize = 60
        progressBar.safePercent = 100
        progressBar.setProgress(to: 1, withAnimation: true)
    }
}

以下是该错误的记录:

在此处输入图像描述

感谢您阅读本文。

标签: iosswift

解决方案


推荐阅读