如何快速创建自己的进度条?

死亡守卫

我要创建自己的自定义进度条,即:NSProgressIndicator使用 swift 我该怎么做?

您可以制作自己的进度指示器,例如:

@IBDesignable
open class ColorfulProgressIndicator: NSView {
    @IBInspectable open var doubleValue: Double = 50 { didSet { needsLayout = true } }
    @IBInspectable open var minValue: Double = 0     { didSet { needsLayout = true } }
    @IBInspectable open var maxValue: Double = 100   { didSet { needsLayout = true } }

    @IBInspectable open var backgroundColor: NSColor = .lightGray { didSet { layer?.backgroundColor = backgroundColor.cgColor } }
    @IBInspectable open var progressColor:   NSColor = .blue      { didSet { progressShapeLayer.fillColor = progressColor.cgColor } }
    @IBInspectable open var borderColor:     NSColor = .clear     { didSet { layer?.borderColor = borderColor.cgColor } }
    @IBInspectable open var borderWidth:     CGFloat = 0          { didSet { layer?.borderWidth = borderWidth } }
    @IBInspectable open var cornerRadius:    CGFloat = 0          { didSet { layer?.cornerRadius = cornerRadius } }

    private lazy var progressShapeLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.fillColor = progressColor.cgColor
        return shapeLayer
    }()

    public override init(frame: NSRect = .zero) {
        super.init(frame: frame)
        configure()
    }

    public required init?(coder: NSCoder) {
        super.init(coder: coder)
        configure()
    }

    // needed because IB doesn't don't honor `wantsLayer`
    open override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        layer = CALayer()
        configure()
    }

    open override func layout() {
        super.layout()
        updateProgress()
    }

    open func animate(to doubleValue: Double? = nil, minValue: Double? = nil, maxValue: Double? = nil, duration: TimeInterval = 0.25) {
        let currentPath = progressShapeLayer.presentation()?.path ?? progressShapeLayer.path

        // stop prior animation, if any
        progressShapeLayer.removeAnimation(forKey: "updatePath")

        // update progress properties
        if let doubleValue = doubleValue { self.doubleValue = doubleValue }
        if let minValue = minValue       { self.minValue = minValue }
        if let maxValue = maxValue       { self.maxValue = maxValue }

        // create new animation
        let animation = CABasicAnimation(keyPath: "path")
        animation.duration = duration
        animation.fromValue = currentPath
        animation.toValue = progressPath
        progressShapeLayer.add(animation, forKey: "updatePath")
    }
}

private extension ColorfulProgressIndicator {
    func configure() {
        wantsLayer = true

        layer?.cornerRadius = cornerRadius
        layer?.backgroundColor = backgroundColor.cgColor
        layer?.borderWidth = borderWidth
        layer?.borderColor = borderColor.cgColor

        layer?.addSublayer(progressShapeLayer)
    }

    func updateProgress() {
        progressShapeLayer.path = progressPath
    }

    var progressPath: CGPath? {
        guard minValue != maxValue else { return nil }
        let percent = max(0, min(1, CGFloat((doubleValue - minValue) / (maxValue - minValue))))
        let rect = NSRect(origin: bounds.origin, size: CGSize(width: bounds.width * percent, height: bounds.height))
        return CGPath(rect: rect, transform: nil)
    }
}

您可以只设置其doubleValue, minValueand maxValue,或者如果您想为更改设置动画,只需:

progressIndicator.animate(to: 75)

例如,下面我设置progressColorborderColor.red,设置borderWidth1,设置cornerRadius10然后我开始动画到75,然后,在它完成之前,触发另一个动画到100(以说明动画可以从它停止的任何地方恢复):

在此处输入图片说明

有很多方法可以实现这一点(所以不要迷失在上面的实现细节中),但它说明创建我们自己的进度指示器非常容易。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章