3

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暂停时,动画的内部计数器也会继续并在动画应该完成时调用完成块。

4

0 回答 0