【问题标题】:Is there a way to observe changes to fractionComplete in UIViewPropertyAnimator有没有办法观察 UIViewPropertyAnimator 中对 fractionComplete 的更改
【发布时间】:2017-04-24 11:04:07
【问题描述】:

我一直在研究 iOS 10 中非常酷的新 UIViewPropertyAnimator 类。它可以让您轻松执行暂停、恢复和反转飞行中的 UIView 动画等操作。过去,您必须操作系统创建的底层 CAAnimations 才能使用 UIView 动画执行此操作。

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

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

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

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

我希望我缺少一些东西。

您可以在 Github 上的以下链接查看基于 UIViewPropertyAnimator 的项目: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,你为什么不在同一点更新滑块呢?
  • @AlineKolczyckiBorges 动画通常从头到尾运行,无需我的代码更新UIViewPropertyAnimator。我可能会暂停动画,或者来回擦洗它,但正常情况是它从头到尾进行。我希望有一种方法可以观察变化,无论这些变化是如何发生的。
  • CADisplayLink 是要走的路
  • 我很确定 fractionComplete 不是动态属性,因此无法观察到使用 KVO 的变化

标签: ios swift uiview uikit uiviewpropertyanimator


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您是否尝试子类化 UIViewPropertyAnimator,然后覆盖 fractionComplete 属性?

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

    【讨论】:

    • fractionComplete 不会动态更新——因此,您不会从这里获得中间值——只有开始和结束状态。
    • fractionComplete 不符合 KVO。您需要设置一个计时器或一个 CADisplayLink 来定期检查它。
    猜你喜欢
    • 1970-01-01
    • 2011-05-24
    • 2013-06-14
    • 1970-01-01
    • 2021-05-20
    • 2015-12-16
    • 2017-08-15
    • 2021-03-30
    • 2018-06-04
    相关资源
    最近更新 更多