Flip between two ViewControllers under the same NavigationController

I mentioned this question and a few questions about the transition of the view / view controller, but so far I have not been able to find a satisfied answer. Most solutions suggest flipping views instead of view controllers. However, the two view controllers in my application have a completely different logic of work and implementation, so I avoid mixing them.

In my application, I have a modal view controller FrontViewController that is built into the NavigationController. After clicking one button to view, the modal view controller should turn to the BackViewController and vice versa. I have 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 the same as me, except that it also translates the navigation bar. Moreover, if I reject the modal view, only the view manager at the top of the stack is fired, while I was not able to get the correct parent / presentation controller to reject all other stack controllers in the modal view.

Thus, I also tried to prevent the viewcontroller stack and use the transitionFromViewController in the 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 runtime error on execution: Parent view controller is using legacy containment in call to -[UIViewController transitionFromViewController:toViewController: duration:options:animations:completion:]

So, how does the transition between two view controllers while preventing them remain on the view manager stack?

+5
source share
5 answers

You can add a custom transition to the level of the navigation controllers before clicking 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 must be false . Otherwise, the default rolling animation will be executed.

+11
source

See this demo for you:

Quick code for flipAnimation:

 let mainStory = UIStoryboard(name: "Main", bundle: nil) let search = mainStory.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController UIView.beginAnimations("animation", context: nil) UIView.setAnimationDuration(1.0) self.navigationController!.pushViewController(search, animated: false) UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromLeft, forView: self.navigationController!.view, cache: false) UIView.commitAnimations() 

FlipViewController Animation

Output:

enter image description here

+8
source

Swift 3.0 + If you are using a UIView animation UIView , make sure your viewController in the UINavigationController stacks:

 let viewController = ViewController(nibName: "xxx", bundle: nil) UIView.transition(with: self.navigationController!.view, duration: 1.0, options: .transitionFlipFromLeft, animations: { self.navigationController?.pushViewController(viewController, animated: false) }, completion: nil) 
+1
source

here is an NSObjectClass Student

 var Arraydata:[Student] = [] func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let arr = Arraydata[indexPath.row] if indexPath.row == arr { let story = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController UIView.beginAnimations("", context: nil) UIView.setAnimationDuration(1.0) UIView.setAnimationCurve(UIViewAnimationCurve.easeInOut) UIView.setAnimationTransition(UIViewAnimationTransition.flipFromRight, for: (self.navigationController?.view)!, cache: false) self.navigationController?.pushViewController(story, animated: true) UIView.commitAnimations() } } 
0
source
  override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(true) // for back button changeTransition() } //btnMap.addTarget(self, action: #selector(searchHotelsResultVC.goToMap), for: .touchUpInside) //btnMap.addTarget(self, action: #selector(MapViewController.backToList), for: .touchUpInside) func goToMap() { // for pushing changeTransition() navigationController?.pushViewController(settingsVC, animated: false) } func backToList() { // for dismiss changeTransition() navigationController?.popViewController(animated: false) dismiss(animated: true, completion: nil) } func changeTransition() { let transition = CATransition() transition.duration = 0.5 transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) //transition.type = kCATransitionPush transition.type = "flip" transition.subtype = kCATransitionFromLeft navigationController?.view.layer.add(transition, forKey: kCATransition) } 
-1
source

Source: https://habr.com/ru/post/1239389/


All Articles