简体   繁体   English

使用UIViewPropertyAnimator按顺序制作UIView的alpha动画

[英]Animating a UIView's alpha in sequence with UIViewPropertyAnimator

I have a UIView that I want to reveal after 0.5 seconds, and hide again after 0.5 seconds, creating a simple animation. 我有一个想要在0.5秒后显示的UIView,并在0.5秒后再次隐藏,创建一个简单的动画。 My code is as follows: 我的代码如下:

    let animation = UIViewPropertyAnimator.init(duration: 0.5, curve: .linear) {
        self.timerBackground.alpha = 1
        let transition = UIViewPropertyAnimator.init(duration: 0.5, curve: .linear) {
            self.timerBackground.alpha = 0
        }
        transition.startAnimation(afterDelay: 0.5)
    }
    animation.startAnimation()

When I test it out, nothing happens. 当我测试它时,没有任何反应。 I assume it's because they're both running at the same time, which would mean they cancel each other out, but isn't that what the "afterDelay" part should prevent? 我认为这是因为它们都在同一时间运行,这意味着它们相互抵消,但这不是“afterDelay”部分应该阻止的吗?

If I run them separately, ie either fading from hidden to visible, or visible to hidden, it works, but when I try to run them in a sequence, it doesn't work. 如果我单独运行它们,即从隐藏变为可见,或从隐藏变为可见,它可以工作,但是当我尝试按顺序运行它时,它不起作用。

My UIView is not opaque or hidden. 我的UIView不是不透明或隐藏的。

You can use Timer , and add appearing / hiding animations blocks on every timer tick to your UIViewPropertyAnimator object. 您可以使用Timer ,并在每个计时器刻度上添加出现/隐藏动画块到您的UIViewPropertyAnimator对象。

Here's a codebase: 这是一个代码库:

@IBOutlet weak var timerBackground: UIImageView!

private var timer: Timer?
private var isShown = false
private var viewAnimator = UIViewPropertyAnimator.init(duration: 0.5, curve: .linear)

override func viewDidLoad() {
    super.viewDidLoad()
    viewAnimator.addAnimations {
        self.timerBackground.alpha = 1
    }
    viewAnimator.startAnimation()
    isShown = true

    self.timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(self.startReversedAction), userInfo: nil, repeats: true)
}

func startReversedAction() {
    // stop the previous animations block if it did not have time to finish its movement
    viewAnimator.stopAnimation(true)
    viewAnimator.addAnimations ({
        self.timerBackground.alpha = self.isShown ? 0 : 1
    })
    viewAnimator.startAnimation()
    isShown  =  !isShown
}

I've implemented the very similar behavior for dots jumping of iOS 10 Animations demo project . 我已经为iOS 10 Animations演示项目的 点跳跃实现了非常相似的行为。

Please, feel free to look at it to get more details. 请随时查看以获取更多详细信息。

Use UIView.animateKeyframes you'll structure your code nicely if you have complicated animations. 使用UIView.animateKeyframes ,如果你有复杂的动画,你将很好地构建你的代码。 If you'll use UIView animations nested within the completion blocks of others, it will probably result in ridiculous indentation levels and zero readability. 如果你将UIView动画嵌套在其他人的完成块中,它可能会导致荒谬的缩进级别和零可读性。

Here's an example: 这是一个例子:

/* Target frames to move our object to (and animate)
   or it could be alpha property in your case... */

let newFrameOne = CGRect(x: 200, y: 50, width: button.bounds.size.width, height: button.bounds.size.height)
let newFrameTwo = CGRect(x: 300, y: 200, width: button.bounds.size.width, height: button.bounds.size.height)

UIView.animateKeyframes(withDuration: 2.0,
                               delay: 0.0,
                             options: .repeat,
                          animations: { _ in
    /* First animation */                                    
    UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.5, animations: { [weak self] in
        self?.button.frame = newFrameOne
    })

    /* Second animation */                                    
    UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: { [weak self] in
        self?.button.frame = newFrameTwo
    })

    /* . . . */  

    }, completion: nil)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM