How to make Segue animation Horizontal without UINavigationController?

Daniele B picture Daniele B · Nov 20, 2015 · Viewed 9.9k times · Source

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?

Answer

Armin picture Armin · Nov 29, 2015

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)

        }) 

    }

}