【问题标题】:How to add an animation in progress bar UIView如何在进度条 UIView 中添加动画
【发布时间】:2021-03-24 11:22:01
【问题描述】:

我想在基于 UIView 的进度条中添加动画。 这是我的代码。

@IBDesignable class PlainHorizontalProgressBar: UIView {
    @IBInspectable var color: UIColor = .green {
        didSet { setNeedsDisplay() }
    }

    var progress: CGFloat = 0 {
        didSet { setNeedsDisplay() }
    }
    
    private let progressLayer = CALayer()
    private let backgroundMask = CAShapeLayer()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupLayers()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupLayers()
    }
    
    private func setupLayers() {
        layer.addSublayer(progressLayer)
    }
    
    override func draw(_ rect: CGRect) {
        backgroundColor = .grey
        backgroundColor?.setFill()
        
        UIBezierPath(roundedRect: rect, cornerRadius: rect.height * 0.25).fill()
        
        backgroundMask.path = UIBezierPath(roundedRect: rect, cornerRadius: rect.height * 0.25).cgPath
        layer.mask = backgroundMask
    
        let progressRect = CGRect(origin: .zero, size: CGSize(width: rect.width * progress, height: rect.height))
    
        progressLayer.frame = progressRect
        layer.addSublayer(progressLayer)
        progressLayer.backgroundColor = color.cgColor
    }

}

这里的场景是,我有 ViewController A 和 ViewController B,我在 ViewController B 上有这个进度条,当我来的时候,我正在将一个值从 ViewController A 分配给 ViewController B(例如:myView.progress = 0.5)到 ViewController B 我的进度条已经填满了一半,但我想要的是,当我来到 ViewController B 时,当我降落在 viewController B 上时,它应该动画并填充在我面前。

【问题讨论】:

    标签: ios swift uiview uiviewanimation uibezierpath


    【解决方案1】:

    这里的主要问题是您的draw 实现是错误的。或者,更好地说,您的 draw 实现根本不应该存在。 draw 中唯一应该发生的事情就是绘图。

    如果您要添加子图层,您需要一个特定的方法,该方法只被调用一次以添加子图层。

    如果您要更改其中一个子图层的框架,则需要另一种特定方法来更改(已经存在的)子图层的框架。将其分开后,如何为帧中的变化设置动画就会更加明显。事实上,因为这是一个图层,所以动画会自动发生。

    class PlainHorizontalProgressBar: UIView {
        
        var color: UIColor = .green {
            didSet { update() }
        }
    
        var progress: CGFloat = 0 {
            didSet { update() }
        }
        
        private let progressLayer = CALayer()
        private let backgroundMask = CAShapeLayer()
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            setupLayers()
        }
        
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            setupLayers()
        }
        
        private func setupLayers() {
            layer.addSublayer(progressLayer)
        }
        
        override func layoutSubviews() {
            super.layoutSubviews()
            backgroundMask.path = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.bounds.size.height * 0.25).cgPath
            layer.mask = backgroundMask
            update()
        }
        
        func update() {
            let progressRect = CGRect(origin: .zero, size: CGSize(width: self.bounds.size.width * progress, height: self.bounds.size.height))
            progressLayer.frame = progressRect
            progressLayer.backgroundColor = color.cgColor
        }
    
    }
    

    关于允许将 progress 值设置在 1 到 100 之间的部分是基本算术问题,留给读者练习。

    【讨论】:

    • 这个问题对我来说仍然存在,让我解释一下我的场景,我有 ViewController A 和 ViewController B,我在 ViewController B 上有这个进度条,我正在将一个值从 ViewController A 分配给 ViewController B (示例:myView.progress = 0.5) 现在当我来到 ViewController B 时,我的进度已经填满了一半,但我想要的是,当我来到 ViewController B 时,这应该在我面前设置动画并填满一半,而这不会发生在这里。
    • 我给你写了一些工作代码来演示如何动画进度。这就是我有兴趣做的所有事情。满足稍后披露的其他规范不是我关心的问题。根据我的解释,很容易解决所有这些问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-10
    • 2011-01-12
    • 2018-04-23
    • 1970-01-01
    • 2020-07-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多