我有一个自定义绘制的进度条,与过渡选项相比,我希望以更流畅的方式进行动画处理。但是它没有像我在下面那样对.curveEaseOut
做出响应。如果将其更改为.transitionCrossDissolve
,则可以使用,但是我希望使用曲线动画。我该如何使用它?
@IBOutlet var experienceProgress: experienceBar!
func updateProgress() {
experienceProgress.progress = 0.5
experienceProgress.setNeedsDisplay()
UIView.transition(with: experienceProgress,
duration: 1.25,
options: UIView.AnimationOptions.curveEaseOut,
animations: {
self.experienceProgress.layer.displayIfNeeded()
})
}
@IBDesignable
class experienceBar: UIView {
var progress:CGFloat = 0
override func draw(_ rect: CGRect) {
let color = UIColor(red: 220/255, green: 0, blue: 80/255, alpha: 1.000)
let rectanglePath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: progress * 132, height: 8.5))
color.setFill()
rectanglePath.fill()
}
}
答案 0 :(得分:3)
根本的问题是您的draw(_:)
是给定时间视图的快照,因此不容易创建动画。要为UIView
对象设置动画,最简单的方法就是使用可设置动画的属性。作为UIView
documentation says:
可以对多个视图属性进行更改,使它们具有动画效果-即,更改属性会创建一个从当前值开始并以您指定的新值结束的动画。
UIView
类的以下属性是可动画的:
frame
bounds
center
transform
alpha
backgroundColor
从技术上讲,从理论上讲您可以做自己的手动动画,但是通常最好首先查看是否可以重构代码以使用以下UIView
个可动画属性之一。
幸运的是,在这种情况下,您可以消除draw(_:)
并将其替换为使用子视图的东西,您可以在其中对子视图的frame
(这是可动画的属性)进行动画处理,以反映“百分比完成”部分。
@IBDesignable
public class CustomProgressView: UIView {
public var progress: CGFloat = 0 { didSet { updateProgress() } }
private var progressView: UIView = {
let progressView = UIView()
progressView.backgroundColor = UIColor(red: 220/255, green: 0, blue: 80/255, alpha: 1)
return progressView
}()
override public init(frame: CGRect = .zero) {
super.init(frame: frame)
configure()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
override public func layoutSubviews() {
super.layoutSubviews()
updateProgress()
}
override public func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
progress = 0.5
}
}
private extension CustomProgressView {
func configure() {
addSubview(progressView)
}
func updateProgress() {
var rect = bounds
rect.size.width *= progress
progressView.frame = rect
}
}
然后您可以做:
UIView.animate(withDuration: 1, delay: 0, options: .curveEaseOut, animations: {
self.progressView.progress = 0.75
}, completion: nil)
一些不相关的观察结果
我不太了解progress * 132
的意图。因此,我只是假设progress
是介于0.0和1.0之间的百分比,并且子视图会越过该百分比。
我在didSet
属性的progress
中自动进行了子视图的更新。视图控制器(或其他控制器)永远不必手动说setNeedsDisplay
或类似的东西。
我将类名更改为以大写字母开头。变量和方法名称以小写字母开头,但类型名称(如类,结构,枚举等)始终以大写字母开头。
我注意到您做了这个@IBDesignable
。如果是这样,通常最好将prepareForInterfaceBuilder
的值设置为有趣的值,以便您可以在IB中更好地查看进度视图。