ios - custom - Voltear entre dos ViewControllers bajo el mismo NavigationController
navigation controller swift 4 example (5)
Me he referido a esta pregunta y a varias preguntas sobre la transición del controlador de vista / vista, pero todavía no he podido encontrar una respuesta satisfactoria. La mayoría de las soluciones sugieren voltear las vistas en lugar de ver los controladores. Sin embargo, los dos controladores de vista en mi aplicación tienen una lógica de operación e implementación totalmente diferente, por lo que evito mezclarlos.
En mi aplicación, tengo un controlador de vista modal FrontViewController
que está incrustado en un NavigationController. Después de presionar un botón en la vista, el controlador de vista modal debe BackViewController
a BackViewController
, y viceversa. Alguna vez intenté lo siguiente en FrontViewController
:
let navi = UINavigationController(rootViewController: backController)
navi.modalPresentationStyle = .CurrentContext
navi.modalTransitionStyle = .FlipHorizontal
self.presentViewController(backController, animated: true, completion: nil)
Esto funciona casi como lo que quiero, excepto que también invierte la barra de navegación. Además, si dejo de lado la vista modal, solo se descarta el controlador de vista en la parte superior de la pila, mientras que no pude obtener el controlador padre / presentador correcto para descartar todos los demás controladores de pila en la vista modal.
Por lo tanto, intenté evitar la pila viewcontroller y usar transitionFromViewController
en FrontViewController
usando el mismo controlador de navegación:
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)
}))
Luego obtuve este error de tiempo de ejecución en la ejecución: Parent view controller is using legacy containment in call to -[UIViewController transitionFromViewController:toViewController: duration:options:animations:completion:]
Entonces, ¿cómo la transición entre dos controladores de vista a la vez que los impide permanecer en la pila del controlador de vista?
Puede agregar una transición personalizada a la capa de controles de navegación justo antes de presionar el controlador de vista.
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)
Tenga en cuenta que el parámetro animated
debe ser false
. De lo contrario, se realizará la animación deslizante predeterminada
Vea esta demostración para usted:
Swift 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()
Salida:
Swift 3.0 + Si utiliza el bloque de animación de UIView
, asegúrese de que su viewController
en UINavigationController
apila:
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)
aquí El estudiante es NSObjectClass
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()
}
}
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)
}