Search code examples
iosswiftuiviewcontrolleruinavigationcontrolleruiviewanimationtransition

Flip between two ViewControllers under the same NavigationController


I had referred to this question and several question about view / view controller transition but still couldn't find an satisfied answer. Most of the solutions suggest to flip the views instead of view controllers. However, the two view controllers in my app have totally different operation and implementation logic, thus I'm avoiding to mix them together.

In my app, I have a modal view controller FrontViewController which is embedded in a NavigationController. After pushing one button on the view, the modal view controller should flip to BackViewController, and vice versa. I had ever tried the following in FrontViewController:

let navi = UINavigationController(rootViewController: backController)
navi.modalPresentationStyle = .CurrentContext
navi.modalTransitionStyle = .FlipHorizontal
self.presentViewController(backController, animated: true, completion: nil)

This works almost as what I want, except that it flips navigation bar as well. Moreover, if I dismiss the modal view, only the view controller on the top of the stack is dismissed, while I failed to get the right parent/presenting controller to dismiss all the other stack controllers in the modal view.

Thus I further tried to prevent viewcontroller stack and use transitionFromViewController in FrontViewController using the same navigation controller instead:

self.navigationController!.addChildViewController(backController)
self.willMoveToParentViewController(nil)

self.navigationController!.transitionFromViewController(self, toViewController: backViewController, duration: 1, options: .TransitionFlipFromLeft, animations:  {}, completion: ({Bool -> Void in
    self.removeFromParentController()
    c.didMoveToParentViewController(self)
}))

Then I got this run time error on executiing: Parent view controller is using legacy containment in call to -[UIViewController transitionFromViewController:toViewController: duration:options:animations:completion:]

So, how to transition between two view controllers while preventing them remain in the view controller stack?


Solution

  • You can add custom transition to the navigation controllers layer just before pushing the view controller.

    let transition = CATransition()
    transition.duration = 0.3
    transition.type = "flip"
    transition.subtype = kCATransitionFromLeft
    self.navigationController?.view.layer.addAnimation(transition, forKey: kCATransition)
    self.navigationController?.pushViewController(viewController!, animated: false)
    

    Note that the animated parameter should be false. Otherwise the default sliding animation will takes place