我UIViewPropertyAnimator
用来制作小contentOffset
动画。
为了让我的视图控制器保持精简,我在要动画的UIScrollView
子类中有动画代码。我最初是在一个UIView.animate
块中制作动画,但我注意到当视图消失(即另一个视图被推到视图顶部)时,动画会跳到最后,所以我试图在动画中实现暂停。此外,我想通过不必要的动画调用来减少 CPU 负载。
var animator: UIViewPropertyAnimator?
...
func showAnimation() {
...
if animator == nil {
animator = UIViewPropertyAnimator(duration: duration, curve: .linear, animations: { [unowned self] in
self.contentOffset = endPoint
})
animator?.addCompletion { [unowned self] (position) in
if position == .end {
self.afterAnimation()
print("completion called")
}
}
}
}
func pauseAnimation() {
if animator?.state == .active {
animator?.pauseAnimation()
}
print("paused animation")
}
该方法afterAnimation()
只是确定是否showAnimation()
要再次调用。
在我的视图控制器中,我基本上有以下内容:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
myScrollView.showAnimation()
}
override func viewWillDisappear(_ animated: Bool) {
viewWillDisappear(animated)
myScrollView.pauseAnimation()
}
现在,只要用户不在另一个屏幕上停留太久,它就可以很好地工作。例如,如果用户调用设置屏幕(被推送到导航堆栈上),则调用 pause 方法 - 正如预期的那样。如果用户在该屏幕上停留的时间过长,那么即使动画没有完成,也会调用动画制作者的完成方法。一旦用户再次关闭设置屏幕,动画就会冻结并且不会继续。
我也尝试过与
animator = UIViewPropertyAnimator.runningPropertyAnimator(withDuration: duration, delay: 0, options: .curveLinear, animations: { [unowned self] in
self.contentOffset = endPoint
print("starting animation")
}) { [unowned self] _ in
self.afterAnimation()
print("completion called")
}
但结果是一样的。一段时间后,完成块被调用。
我怎样才能最好地解决这个问题?谢谢!
编辑:通过不同的打印语句,我慢慢有了这样的想法,即使在animator
暂停时,动画的内部计数器也会继续并在动画应该完成时调用完成块。