Ivan Cantarino
Ivan Cantarino

Reputation: 3246

Run two animations simultaneously

I'm trying to create an animation with two views and I've encountered some unexpected behaviors while performing them.

I want to animate both views position while doing a second animation which is transitionFlipFromBottom

Here's the code:

let initialFrame = CGRect(x: xpos, y: -310, width: 300, height: 300)

let firstView = UIView()
firstView.backgroundColor = .red
firstView.frame = initialFrame

let secondView = UIView()
secondView.backgroundColor = .white
secondView.frame = initialFrame
secondView.isHidden = false


self.view.addSubview(firstView)
self.view.addSubview(secondView)


// Here I try to move the views on screen while fliping them
UIView.animate(withDuration: 1, delay: 0, options: .curveEaseOut, animations: {
    secondView.center = self.view.center
    firstView.center = self.view.center
    self.flip(firstView: firstView, secondView: secondView)
}, completion: nil)



// This function flips the views vertically while it animates the transition from the first to the second view
fileprivate func flip(firstView: UIView, secondView: UIView) {
    let transitionOptions: UIViewAnimationOptions = [.transitionFlipFromBottom, .showHideTransitionViews]
    UIView.transition(with: firstView, duration: 0.5, options: transitionOptions, animations: {
        firstView.isHidden = true
    })

    UIView.transition(with: secondView, duration: 0.5, options: transitionOptions, animations: {
        secondView.isHidden = false
    })
}

The code above fails to execute both animations at the same time.

It only works if I place the flip function call inside the completion block, after the first animation (moving frame) finishes, as the following:

UIView.animate(withDuration: 1, delay: 0, options: .curveEaseOut, animations: {
    secondView.center = self.view.center
    firstView.center = self.view.center
}, completion: {(_) in
    self.flip(firstView: dummyView, secondView: newGroupView)
})

I have even tried to use UIView.animateKeyframes but it still doesn't work.

Am I missing something here?

Thank you.

Upvotes: 5

Views: 5759

Answers (1)

Rob
Rob

Reputation: 437552

A couple of things:

  1. In transition, specify .allowAnimatedContent option.

  2. Defer the animation:

    DispatchQueue.main.async {
        UIView.animate(withDuration: 1, delay: 0, options: [.curveEaseOut], animations: {
            secondView.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY)
            firstView.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY)
            self.flip(firstView: firstView, secondView: secondView)
        }, completion: { _ in
        })
    }
    
  3. Somewhat unrelated, you don't want:

    secondView.center = self.view.center
    

    Instead, do:

    secondView.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY)
    

    You want to set secondView.center in the coordinate space of the bounds of view, not in view's superview.

Upvotes: 4

Related Questions