UIViewPropertyAnimator 不尊重持续时间和延迟参数

Posted

技术标签:

【中文标题】UIViewPropertyAnimator 不尊重持续时间和延迟参数【英文标题】:UIViewPropertyAnimator not respecting duration and delay parameters 【发布时间】:2020-05-03 10:41:09 【问题描述】:

我的应用中有一个非常奇怪的问题。我正在使用UIViewPropertyAnimatorUIImageView 中的变化图像设置动画。

听起来像是微不足道的任务,但出于某种原因,我的视图最终会立即改变图像,所以我最终得到的图像以光速闪烁,而不是给定的持续时间和延迟参数。

代码如下:

private lazy var images: [UIImage?] = [
    UIImage(named: "widgethint"),
    UIImage(named: "shortcuthint"),
    UIImage(named: "spotlighthint")
]
private var imageIndex = 0
private var animator: UIViewPropertyAnimator?

override func viewDidAppear(_ animated: Bool) 
    super.viewDidAppear(animated)
    animator = repeatingAnimator()


override func viewDidDisappear(_ animated: Bool) 
    super.viewDidDisappear(animated)
    animator?.stopAnimation(true)


private func repeatingAnimator() -> UIViewPropertyAnimator 
    return .runningPropertyAnimator(withDuration: 2, delay: 6, options: [], animations: 
        self.imageView.image = self.images[self.imageIndex]
    , completion:  pos in
        if self.imageIndex >= self.images.count - 1 
            self.imageIndex = 0
         else 
            self.imageIndex += 1
        
        self.animator = self.repeatingAnimator()
    )

因此,根据代码动画应该需要 2 秒才能完成并在 6 秒延迟后开始,但它会立即开始并需要几毫秒才能完成,所以我最终得到了可怕的幻灯片。为什么会这样?

我也尝试使用UIViewPropertyAnimator(duration: 2, curve: .linear) 和调用repeatingAnimator().startAnimation(afterDelay: 6),但结果是一样的。

【问题讨论】:

【参考方案1】:

好的,我已经想通了,但是使用“现代”动画 API 无法完成如此简单的任务仍然有点烦人。

因此,UIViewPropertyAnimator 显然不支持在UIImageView 中为图像设置动画,在调试过程中我尝试为视图的背景颜色设置动画,它按预期工作。所以我不得不改用Timer 和旧的UIView.transition(with:) 方法

这是工作代码:

private let animationDelay: TimeInterval = 2.4

private var animationTimer: Timer!

override func viewDidAppear(_ animated: Bool) 
    super.viewDidAppear(animated)
    setAnimation(true)


override func viewDidDisappear(_ animated: Bool) 
    super.viewDidDisappear(animated)
    setAnimation(false)


private func setAnimation(_ enabled: Bool) 
    guard enabled else 
        animationTimer?.invalidate()
        animationTimer = nil
        return
    
    animationTimer = Timer.scheduledTimer(withTimeInterval: animationDelay, repeats: true)  _ in
        UIView.transition(with: self.imageView, duration: 0.5, options: [.curveLinear, .transitionCrossDissolve], animations: 
            self.imageView.image = self.images[self.imageIndex]
        , completion:  succ in
            guard succ else 
                return
            
            if self.imageIndex >= self.images.count - 1 
                self.imageIndex = 0
             else 
                self.imageIndex += 1
            
        )
    

希望它可以在将来为某人省去一些麻烦

【讨论】:

以上是关于UIViewPropertyAnimator 不尊重持续时间和延迟参数的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 UIViewPropertyAnimator 中使用“unowned”

UIViewPropertyAnimator 的反弹效果

完成块内的 UIViewPropertyAnimator 状态?

NSLayoutConstraints 的 UIViewPropertyAnimator 使视图消失

UIViewPropertyAnimator 开头有短动画片段

UIViewPropertyAnimator - 简单地停止所有动画,而不是特定的?