Search code examples
iosswiftuinavigationcontrollersegueuisplitviewcontroller

How to make Segue animation Horizontal without UINavigationController?


I am using a UISplitViewController, with a MasterViewController and DetailViewController, without UINavigationControllers.

Currenly the segue animation for master->detail, triggered by

performSegueWithIdentifier("showDetail", sender: self)

consists in the DetailViewController showing up from the bottom upwards.

How can I make that animation showing left-wards?


Solution

  • I've recently needed to have more control of how the segues are being performed, so I made my custom segue classes which all perform the transition in different directions. Here's one of the implementations:

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

    This one will have a "right to left" transition. You can modify this function for your needs by simply changing the initial and ending positions of the source and destination view controller.

    Also don't forget that you need to mark your segue as "custom segue", and to assign the new class to it.

    UPDATE: Added Swift 3 version

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