Search code examples
iosswiftcore-animation

How to sequence two animations with delay in between


I have a UIImageView which i want to rotate 180 degrees, taking up 1 second, then i want to wait 1 second at this position, then rotate 180 degrees back to the original position taking up 1 second.

How do i accomplish this? I've tried a 100 approaches and it keeps snapping back instead of rotating back

EDIT: I forgot to add i need this to repeat indefinitely


Solution

  • You can perform the second animation in the completionHandler presented on UIView.animate

    let duration = self.transitionDuration(using: transitionContext)
    
    let firstAnimDuration = 0.5
    UIView.animate(withDuration: firstAnimDuration, animations: {
        /* Do here the first animation */
    }) { (completed) in
    
       let secondAnimDuration = 0.5
       UIView.animate(withDuration: secondAnimDuration, animations: { 
           /* Do here the second animation */
       })
    }
    

    Now you could have another problem.

    If you rotate your view with the CGAffineTransform and for every animation you assign a new object of this type to your view.transform, you will lose the previous transform operation

    So, according to this post: How to apply multiple transforms in Swift, you need to concat the transform operation

    Example with 2 animation block

    This is an example to made a rotation of 180 and returning back to origin after 1 sec:

    let view = UIView.init(frame: CGRect.init(origin: self.view.center, size: CGSize.init(width: 100, height: 100)))
    view.backgroundColor = UIColor.red
    self.view.addSubview(view)
    
    var transform = view.transform
    transform = transform.rotated(by: 180)
    
    UIView.animate(withDuration: 2, animations: {
        view.transform = transform
    }) { (completed) in
    
        transform = CGAffineTransform.identity
        UIView.animate(withDuration: 2, delay: 1, options: [], animations: { 
            view.transform = transform
        }, completion: nil)
    }
    

    Example of .repeat animation and .autoreverse

    The .animate method give you the ability to set some animation options. In particular the structure UIViewAnimationOptions contains:

    1. .repeat, which repeat indefinitely your animation block
    2. .autoreverse, which restore your view to the original status

    With this in mind you could do this:

    var transform = view.transform.rotated(by: 180)
    UIView.animate(withDuration: 2, delay: 0, options: [.repeat, .autoreverse], animations: {
         self.myView.transform = transform
    })
    

    But you need a delay between the two animations, so you need to do this trick:

    Example of recursive animation and a delay of 1 sec

    Just create a method inside your ViewController which animate your view. In the last completionHandler, just call the method to create a infinite loop.

    Last you need to call the method on viewDidAppear to start the animation.

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    
        self.animation()
    }
    
    
    func animation() {
        var transform = view.transform
        transform = transform.rotated(by: 180)
    
        UIView.animate(withDuration: 2, delay: 0, options: [], animations: {
    
            self.myView.transform = transform
    
        }) { bool in
            transform = CGAffineTransform.identity
    
            UIView.animate(withDuration: 2, delay: 1, options: [], animations: {
    
                self.myView.transform = transform
    
            }, completion: { bool in
                self.animation()
            })
        }
    }