有没有办法观察 UIViewPropertyAnimator 中 fractionComplete 的变化

Is there a way to observe changes to fractionComplete in UIViewPropertyAnimator

我一直在关注 iOS 10 中非常酷的新 UIViewPropertyAnimator class。它可以让你 轻松地 做一些事情,比如暂停、恢复和反转飞行中的 UIView 动画。过去,您必须操纵系统创建的底层 CAAnimations 才能使用 UIView 动画来做到这一点。

新的UIViewPropertyAnimatorclass有一个属性fractionComplete。它从 0.0(动画开始)到 1.0(动画结束)不等。如果更改该值,则可以 "scrub" 动画从头到尾。

我在 Github 上有一个名为 KeyframeViewAnimations 的演示项目,它允许您使用滑块使用相当神秘的 CAAnimation 技巧来回擦洗 UIView 和 CAAnimations。随着动画的运行,滑块从开始移动到结束以显示动画的进度。该项目是在 Swift 发布之前用 Objective-C 编写的,但底层技术在 Objective-C 或 Swift.

中是相同的

我决定使用 UIViewPropertyAnimator 创建一个等效项目。有一些怪癖,但它相当简单。我无法弄清楚如何干净地做的一件事是观察动画的 fractionComplete 属性 的进度,以便我可以随着动画的进行更新滑块。我尝试在 fractionComplete 属性 上设置 KVO(键值观察),但在动画完成之前它不会触发 KVO 通知。

我最后做的是设置一个以非常小的间隔运行的计时器,并重复查询 UIViewPropertyAnimatorfractionComplete 属性 并随着进度更新滑块.它有效,但它不是一种非常干净的做事方式。如果有办法通知动画进度就更好了。

我希望我遗漏了什么。

您可以在 Github 上看到基于 UIViewPropertyAnimator 的项目 link: UIViewPropertyAnimator-test.

从动画师那里获取进度值的代码是这段代码:

func startTimer(_ start: Bool) {
  if start {
    timer = Timer.scheduledTimer(withTimeInterval: 0.02,
     repeats: true) {
        timer in
        var value = Float(self.viewAnimator.fractionComplete)
        if self.animatingBackwards {
          value = 1 - value
        }
        self.animationSlider.value = value
     }
  }
  else {
    self.timer?.invalidate()
  }
}

我应该将上面的代码转换为使用 CADisplayLink 计时器而不是普通计时器 (NSTimer),但我希望有更好的方法。

您是否尝试继承 UIViewPropertyAnimator 然后重写 fractionComplete 属性?

class MyPropertyAnimator : UIViewPropertyAnimator {
    override var fractionComplete: CGFloat {
        didSet {
            print("didSetFraction")
        }
    }
}

仅供参考,经过研究后,答案似乎是否定的,随着动画的进行,无法获得更新。您必须设置一个计时器(TimerCADisplayLink 并在每次触发时更新您的进度值。