在同一个NavigationController下的两个ViewControllers之间翻转

时间:2015-12-29 04:13:20

标签: ios swift uiviewcontroller uinavigationcontroller uiviewanimationtransition

我曾提到this question以及有关视图/视图控制器转换的几个问题,但仍无法找到满意的答案。大多数解决方案建议翻转视图而不是视图控制器。但是,我的应用程序中的两个视图控制器具有完全不同的操作和实现逻辑,因此我避免将它们混合在一起。

在我的应用中,我有一个模态视图控制器FrontViewController,它嵌入在NavigationController中。在视图上按下一个按钮后,模态视图控制器应翻转到BackViewController,反之亦然。我曾在FrontViewController尝试过以下内容:

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

这几乎和我想要的一样,除了翻转导航栏。此外,如果我关闭模态视图,只有堆栈顶部的视图控制器被解除,而我无法让正确的父/呈现控制器解除模态视图中的所有其他堆栈控制器。

因此,我进一步尝试阻止viewcontroller堆栈,并使用相同的导航控制器在transitionFromViewController中使用FrontViewController

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)
}))

然后我在执行时遇到了这个运行时错误:Parent view controller is using legacy containment in call to -[UIViewController transitionFromViewController:toViewController: duration:options:animations:completion:]

那么,如何在两个视图控制器之间进行转换同时防止它们保留在视图控制器堆栈中?

6 个答案:

答案 0 :(得分:15)

您可以在推动视图控制器之前将自定义过渡添加到导航控制器层。

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)

请注意,animated参数应为false。否则,将发生默认的滑动动画

答案 1 :(得分:8)

为您查看此演示:

flipAnimation的swift代码:

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

输出:

enter image description here

答案 2 :(得分:3)

迅速5-我个人喜欢使用这种方法。

//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)
}

答案 3 :(得分:2)

Swift 3.0 + 应该使用UIView的动画块,确保viewController堆放UINavigationController

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)

答案 4 :(得分:1)

     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)

    }

答案 5 :(得分:0)

此处学生为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()

        }
    }