简体   繁体   中英

Would setting a UIView property explicitly stop/finish an existing animation which was started using UIViewPropertyAnimator on the same property

My current level of iOS dev knowledge is that I am still very new to it and in the learning stage. Giving this info so that experts can answer accordingly :)

As per the Stanford's course for iOS development it was said that an animation for a UIView property would be interrupted if another animation starts for the same property (more specifically the new animation starts working on one of the properties of the previous animation).

Link to the exact point in the video where this was taught https://youtu.be/84ZhYhAwYqo?t=209

The same rather similar thing was also said as an answer to a question on stackoverflow also. Direct link to answer https://stackoverflow.com/a/3076451/8503233

But when I tried this it didn't happen.

To test this I made a simple app where a button click started animating a view using UIViewPropertyAnimator.runningPropertyAnimator, where it changed the alpha to 0. Duration was set to 10 seconds so that I had plenty of time to trigger another animation.

Then another button will start an animation changing the alpha of the same view to 1. I expected that when the second animation will start, it will cause the first animation to stop and its completion handler to be called with the value of UIViewAnimatingPosition as .current.

But what I found that even when the second animation started, the first animation was still running and after running for its full duration, the completion handler was called with UIViewAnimatingPosition as .end.

This is absolutely opposite to what I read in the sources I gave above. Please help. What exactly is happening here. Will share the app code if asked for. Thanks!!!

EDIT1:

View controller code

class MyViewController: UIViewController {

    @IBOutlet weak var viewToAnimate: UIView!
    @IBOutlet weak var statusView: UIView!

    @IBAction func buttonAnimate1(_ sender: UIButton) {
        UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 5, delay: 0, options: [], animations: {
            self.viewToAnimate.alpha = 0.1
        }, completion: {position in
            switch position {
            case .start:
                print("In animation 1 completion block with position = start")
            case .current:
                print("In animation 1 completion block with position = current")
            case .end:
                print("In animation 1 completion block with position = end")
            }
            self.statusView.backgroundColor = UIColor.brown
        })
    }


    @IBAction func buttonAnimate2(_ sender: UIButton) {
        UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 5, delay: 0, options: [.beginFromCurrentState], animations: {
            self.viewToAnimate.alpha = 1
        }, completion: {position in
            switch position {
            case .start:
                print("In animation 2 completion block with position = start")
            case .current:
                print("In animation 2 completion block with position = current")
            case .end:
                print("In animation 2 completion block with position = end")
            }
            self.statusView.backgroundColor = UIColor.green
        })
    }


    @IBAction func buttonRestore(_ sender: UIButton) {
        viewToAnimate.alpha = 1
        statusView.backgroundColor = UIColor.yellow
    }
}

Test Steps:

In the simulator I press Animate1 button and then after about 1 second, I press Animate2 button.

Output on console:

In animation 1 completion block with position = end
In animation 2 completion block with position = end

In the comments from @matt, what's told is that animations are now additive. This clarifies things a lot but Apple's documentation for addAnimations(_:delayFactor:) says and I quote

If the animation block modifies a property that is being modified by a different property animator, then the animators combine their changes in the most appropriate way. For many properties, the changes from each animator are added together to yield a new intermediate value. If a property cannot be modified in this additive manner, the new animations take over as if the beginFromCurrentState option had been specified for a view-based animation.

So if a new animation takes over as beginFromCurrentState either implicitly or explicitly, then shouldn't the first animation stop with the state as .current when the new animation takes over?

You are consulting ancient history (the answer you cite is from 2010!). It used to be true that with view animation, ordering an animation on a view property already being animated would cancel the existing animation suddenly. But in more recent versions of iOS, view animations have been additive , meaning that a new animation will, by default, be combined smoothly with an existing in-flight animation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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