Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 258
whitney13625 Avatar asked Dec 29 '15 04:12

whitney13625


2 Answers

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

like image 110
Johnykutty Avatar answered Nov 04 '22 03:11

Johnykutty


Swift 5 - I personally like using this approach.

//PUSH
let secondVC = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "secondVC") as! SecondVC
self.navigationController?.pushViewController(secondVC, animated: false)
UIView.transition(from: self.view, to: secondVC.view, duration: 0.85, options: [.transitionFlipFromLeft])

//POP
let firstVC = self.navigationController?.viewControllers[(self.navigationController?.viewControllers.count ?? 2) - 2] as? FirstVC
if let firstView = firstVC?.view{
    self.navigationController?.popViewController(animated: false)
    UIView.transition(from: self.view, to: firstView, duration: 0.85, options: [.transitionFlipFromRight])
} else {
    self.navigationController?.popViewController(animated: true)
}
like image 34
Paul Mayer Avatar answered Nov 04 '22 03:11

Paul Mayer