如何在 Swift 中使用 CoreGraphics 显示静态非动画进度条?

How to show a static NON-animated progress bar using CoreGraphics in Swift?

我想制作一个完全没有动画的静态进度条。我只想像 一样填充橙色部分,这张图片显示了(3 个中的 1 个)的进度,我想知道如何完成这个视图(3 个中的 2 个)并最终完成进度条,如(3 个中的 3 个)。

谢谢您,我们将不胜感激。

这是一个可以设计的作品 class

import Foundation
import UIKit

@IBDesignable
class StaticLoad: UIView {

    enum Progress {
        case Empty
        case Filled(num: Int)
        case Full
    }

    @IBInspectable public var progressColor: UIColor?  {
        didSet {
            updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
        }
    }

    @IBInspectable public var nonProgressColor: UIColor = .gray {
        didSet {
            updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
        }
    }

    @IBInspectable public var numberOfSteps: Int = 3 {
        didSet {
            redrawSteps(step: numberOfSteps)
            updateColor(progressColor: progressColor ?? self.tintColor, nonProgressColor: nonProgressColor)
        }
    }

    @IBInspectable public var filledProgess: Int = 1 {
        didSet {
            if filledProgess >= numberOfSteps {
                filledProgess = numberOfSteps
                progress = .Full
            }
            if filledProgess <= 0 {
                filledProgess = 0
                progress = .Empty
            } else {
                progress = .Filled(num: filledProgess)
            }
            updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
        }
    }

    private var tip: CGFloat = 5
    private var progress: Progress = .Empty
    private var progressLayers: [CAShapeLayer] = []

    private func updateColor(progressColor: UIColor, nonProgressColor: UIColor) {
        switch progress {
        case .Empty:
            progressLayers.forEach { [=10=].fillColor = nonProgressColor.cgColor }
        case let .Filled(num):
            progressLayers.dropFirst(num).forEach { [=10=].fillColor = nonProgressColor.cgColor }
            progressLayers.dropLast(progressLayers.count - num).forEach { [=10=].fillColor = progressColor.cgColor }
        case .Full :
            progressLayers.forEach { [=10=].fillColor = progressColor.cgColor }
        }
    }

    private func redrawSteps(step: Int) {
        progressLayers.forEach { [=10=].removeFromSuperlayer() }
        progressLayers.removeAll()
        if step == 0 {
            let layer = CAShapeLayer()
            layer.frame = self.bounds
            progressLayers.append(layer)
        } else {
            var topLeft = CGPoint(x: 0, y: 0)
            let cgStep = CGFloat(step)
            let avaibleWidth = self.bounds.width - (2 * (cgStep - 1))
            let spacePerStep = avaibleWidth / cgStep
            let height = bounds.height
            let halfHeight = height / 2
            for i in 0..<step {

                let layer = CAShapeLayer()
                let bezier = UIBezierPath()
                bezier.move(to: topLeft)
                bezier.addLine(to: CGPoint(x: topLeft.x + spacePerStep, y: topLeft.y))
                if i + 1 != step {
                    bezier.addLine(to: CGPoint(x: topLeft.x + spacePerStep + tip, y: topLeft.y + halfHeight))
                }
                bezier.addLine(to: CGPoint(x: topLeft.x + spacePerStep, y: topLeft.y + height))
                bezier.addLine(to: CGPoint(x: topLeft.x, y: topLeft.y + height))
                if i != 0 {
                    bezier.addLine(to: CGPoint(x: topLeft.x + tip, y: topLeft.y + halfHeight))
                }
                bezier.close()
                layer.path = bezier.cgPath
                progressLayers.append(layer)
                self.layer.addSublayer(layer)

                topLeft.x = topLeft.x + spacePerStep + 2
            }
        }
    }

    override func layoutSubviews() {
        redrawSteps(step: numberOfSteps)
        updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
    }

}

您所要做的就是从情节提要中获取一个 UIView 并进行自定义 class StaticLoad。您可以通过代码或故事板更改 numberOfSteps 属性 来指定进度条中的条数,并通过 filledProgress

填充条

如果您想要更大的箭头,只需更改 tip 属性,或为 bezierPath 指定其他路径。

如果你不知道,@IBDesignable(建议如果class是可设计的,因为要不断编译,建议放在另一个框架而不是同一个项目)允许故事板渲染视图,@IBInspectable 允许通过故事板设置变量。

这是一个未优化的工作示例。