Search code examples
iosxcodeswiftsegueuistoryboardsegue

iOS custom Segue - Slide over effect


I am trying to build a custom segue for the 1st time. The desired result is to create the new ViewController behind the previous one, then to make the previous one slide like if it was ejected/removed from the screen. My problem Is I was not able to do that. It's ok if I create the new one below the previous one (in this case both are sliding up, one ejecting the other one inserting) but this is not what i'm trying to do. The only thing that I managed to do was sliding the previous one up alone but there's a black background below it rather than the new view...

Here is my code (both are scrolling on that one, that's not the expected result) :

override func perform() {

        let viewControllerToRemove = self.sourceViewController.view as UIView!
        let viewControllerToShow = self.destinationViewController.view as UIView!

        let screenWidth = UIScreen.mainScreen().bounds.size.width
        let screenHeight = UIScreen.mainScreen().bounds.size.height



        viewControllerToShow.frame = CGRectMake(0.0, screenHeight, screenWidth, screenHeight)

        let window = UIApplication.sharedApplication().keyWindow
        window?.insertSubview(viewControllerToShow, aboveSubview: viewControllerToRemove)


        UIView.animateWithDuration(0.6, animations: { () -> Void in

            viewControllerToShow.frame = CGRectOffset(viewControllerToShow.frame, 0.0, -screenHeight)
            viewControllerToRemove.frame = CGRectOffset(viewControllerToRemove.frame, 0.0, -screenHeight)

            }) { (Finished) -> Void in
                self.sourceViewController.presentViewController(self.destinationViewController as UIViewController,
                    animated: false,
                    completion: nil)

        }
    }

Any help would be welcome, thanks in advance !


Solution

  • You should use a transition manager, see these delegate: UIViewControllerAnimatedTransitioning and UIViewControllerTransitioningDelegate

    For your animation it will be a lot easier if there is a global container because in your animation only one view is animated.

    With the transition manager both views are in a transition container so you could put destinationView as a visible background.

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
    
        // get reference to our fromView, toView and the container view that we should perform the transition in
        let container = transitionContext.containerView()
        let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
        let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!
    

    Then set frames to have both views at the same place and just do something like this:

    container.addSubview(toView)
    container.addSubview(fromView)
    container.sendSubviewToBack(toView)
    

    When you will animate fromView, you will see toView in the background this time.

    More informations on this link: http://mathewsanders.com/animated-transitions-in-swift/