如何使Segueanimation水平没有UINavigationController?

我正在使用一个UISplitViewController ,与一个MasterViewControllerDetailViewController ,没有UINavigationController

当然,Seguanimation为master-> detail,触发

 performSegueWithIdentifier("showDetail", sender: self) 

在从下往上显示的DetailViewController

我怎样才能使animation显示左侧?

我最近需要更多的控制如何执行,所以我做了我自定义的inheritance类,所有这些都在不同的方向进行转换。 以下是其中一个实现:

Swift 2.x

 override func perform() { //credits to http://www.appcoda.com/custom-segue-animations/ let firstClassView = self.sourceViewController.view let secondClassView = self.destinationViewController.view let screenWidth = UIScreen.mainScreen().bounds.size.width let screenHeight = UIScreen.mainScreen().bounds.size.height secondClassView.frame = CGRectMake(screenWidth, 0, screenWidth, screenHeight) if let window = UIApplication.sharedApplication().keyWindow { window.insertSubview(secondClassView, aboveSubview: firstClassView) UIView.animateWithDuration(0.4, animations: { () -> Void in firstClassView.frame = CGRectOffset(firstClassView.frame, -screenWidth, 0) secondClassView.frame = CGRectOffset(secondClassView.frame, -screenWidth, 0) }) {(Finished) -> Void in self.sourceViewController.navigationController?.pushViewController(self.destinationViewController, animated: false) } } } 

这个将会有一个“从右到左”的过渡。 您只需更改源视图和目标视图控制器的起始位置和结束位置即可根据需要修改此function。

另外不要忘记,你需要将你的segue标记为“custom segue”,并将新类指定给它。

更新:增加了Swift 3版本

Swift 3

 override func perform() { //credits to http://www.appcoda.com/custom-segue-animations/ let firstClassView = self.source.view let secondClassView = self.destination.view let screenWidth = UIScreen.main.bounds.size.width let screenHeight = UIScreen.main.bounds.size.height secondClassView?.frame = CGRect(x: screenWidth, y: 0, width: screenWidth, height: screenHeight) if let window = UIApplication.shared.keyWindow { window.insertSubview(secondClassView!, aboveSubview: firstClassView!) UIView.animate(withDuration: 0.4, animations: { () -> Void in firstClassView?.frame = (firstClassView?.frame.offsetBy(dx: -screenWidth, dy: 0))! secondClassView?.frame = (secondClassView?.frame.offsetBy(dx: -screenWidth, dy: 0))! }, completion: {(Finished) -> Void in self.source.navigationController?.pushViewController(self.destination, animated: false) }) } } 

这听起来好像新的视图控制器模态地呈现。 如果将detailViewControllerembedded到UINavigationController并推送新的控制器,则它将从右向左进行animation显示,并且默认情况下也应显示后退button。

在UINavigationControllers中embedded你的视图控制器。

根据SplitViewController模板: 在这里输入图像说明

在较小的设备上,将不得不使用Master的navigationController。

此外,这个问题已经在这里 , 这里和这里得到解答

更多来自“ 视图控制器编程指南” :

在屏幕上显示视图控制器有两种方法:将其embedded到容器视图控制器中或呈现它。 容器视图控制器提供了一个应用程序的主导航…。

在故事板中,将某些内容embedded到导航控制器中并不困难。 点击您要embedded的视图控制器,然后点击编辑器 – >embedded – >导航控制器。

Swift 3.0

Armin的解决scheme适用于swift 3. New – > File – > Cocoa Touch Class – > Class:…(子类:UIStoryboardSegue)。

 import UIKit class SlideHorSegue: UIStoryboardSegue { override func perform() { //credits to http://www.appcoda.com/custom-segue-animations/ let firstClassView = self.source.view let secondClassView = self.destination.view let screenWidth = UIScreen.main.bounds.size.width let screenHeight = UIScreen.main.bounds.size.height secondClassView?.frame = CGRect(x: screenWidth, y: 0, width: screenWidth, height: screenHeight) if let window = UIApplication.shared.keyWindow { window.insertSubview(secondClassView!, aboveSubview: firstClassView!) UIView.animate(withDuration: 0.4, animations: { () -> Void in firstClassView?.frame = (firstClassView?.frame)!.offsetBy(dx: -screenWidth, dy: 0) secondClassView?.frame = (secondClassView?.frame)!.offsetBy(dx: -screenWidth, dy: 0) }) {(Finished) -> Void in self.source.navigationController?.pushViewController(self.destination, animated: false) } } } } 

在故事板中:将您的segue标记为“custom segue”,并将新类指定给它。

注意:如果你的detailesVC中有一个UIScrollView,这将不起作用。

当你有一个紧凑的屏幕, “显示细节” segue自动退回到模态segue。所以你的DetailViewController将作为默认的模态segue垂直出现。

你可以使用一个UIViewControllerTransitioningDelegate来定制一个模态segue的animation。

这是一个实现水平animation的例子:
1.设置transitioningDelegate,它是委托方法

 class MasterViewController: UITableViewController,UIViewControllerTransitioningDelegate { //prepare for segue override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "showDetail" { let detailVC = segue.destinationViewController as! DetailViewController detailVC.transitioningDelegate = self // detailVC.detailItem = object//Configure detailVC } } //UIViewControllerTransitioningDelegate func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return LeftTransition() } func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { let leftTransiton = LeftTransition() leftTransiton.dismiss = true return leftTransiton } } 

2:自定义的UIViewControllerAnimatedTransitioning:LeftTransition

 import UIKit class LeftTransition: NSObject ,UIViewControllerAnimatedTransitioning { var dismiss = false func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval { return 2.0 } func animateTransition(transitionContext: UIViewControllerContextTransitioning){ // Get the two view controllers let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)! let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)! let containerView = transitionContext.containerView()! var originRect = containerView.bounds originRect.origin = CGPointMake(CGRectGetWidth(originRect), 0) containerView.addSubview(fromVC.view) containerView.addSubview(toVC.view) if dismiss{ containerView.bringSubviewToFront(fromVC.view) UIView.animateWithDuration(transitionDuration(transitionContext), animations: { () -> Void in fromVC.view.frame = originRect }, completion: { (_ ) -> Void in fromVC.view.removeFromSuperview() transitionContext.completeTransition(true ) }) }else{ toVC.view.frame = originRect UIView.animateWithDuration(transitionDuration(transitionContext), animations: { () -> Void in toVC.view.center = containerView.center }) { (_) -> Void in fromVC.view.removeFromSuperview() transitionContext.completeTransition(true ) } } } }