我有一个自定义 UIView,它使用 Core Graphics 调用来绘制其内容。一切正常,但现在我想要动画影响显示的值的变化。我有一个自定义属性可以在我的自定义 UView 中实现此目的:
var _anime: CGFloat = 0
var anime: CGFloat {
set {
_anime = newValue
for(gauge) in gauges {
gauge.animate(newValue)
}
setNeedsDisplay()
}
get {
return _anime
}
}
我已经从 ViewController 开始了动画:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.emaxView.anime = 0.5
UIView.animate(withDuration: 4) {
DDLogDebug("in animations")
self.emaxView.anime = 1.0
}
}
这不起作用 - 动画值确实从 0.5 更改为 1.0,但它会立即更改。对动画 setter 有两次调用,一次调用值为 0.5,然后立即调用一次值为 1.0。如果我更改属性,我会将动画设置为标准 UIView 属性,例如alpha,它工作正常。
我有 Android 背景,所以整个 iOS 动画框架对我来说看起来就像黑魔法。除了预定义的 UIView 属性之外,还有其他方法可以对属性进行动画处理吗?
下面是动画 View 应该看起来的样子 - 它大约每 1/2 秒获得一个新值,我希望指针在这段时间内从前一个值平滑地移动到下一个值。更新它的代码是:
open func animate(_ progress: CGFloat) {
//DDLogDebug("in animate: progress \(progress)")
if(dataValid) {
currentValue = targetValue * progress + initialValue * (1 - progress)
}
}
更新后调用 draw()
会使其使用新的指针位置重新绘制,并在 initialValue
和 targetValue
之间进行插值
最佳答案
简短回答:使用 CADisplayLink
每 n 帧调用一次。示例代码:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let displayLink = CADisplayLink(target: self, selector: #selector(animationDidUpdate))
displayLink.preferredFramesPerSecond = 50
displayLink.add(to: .main, forMode: .defaultRunLoopMode)
updateValues()
}
var animationComplete = false
var lastUpdateTime = CACurrentMediaTime()
func updateValues() {
self.emaxView.animate(0);
lastUpdateTime = CACurrentMediaTime()
animationComplete = false
}
func animationDidUpdate(displayLink: CADisplayLink) {
if(!animationComplete) {
let now = CACurrentMediaTime()
let interval = (CACurrentMediaTime() - lastUpdateTime)/animationDuration
self.emaxView.animate(min(CGFloat(interval), 1))
animationComplete = interval >= 1.0
}
}
}
代码可以改进和概括,但它正在完成我需要的工作。
关于ios - 如何在 iOS 中为自定义属性设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41540897/