Custom View Transition without using storyboards (Swift)

I have two views that I would like to make using the swipe transition style, and I did it when there is a segue to act, but I don’t have it, so I don’t know how to apply my animation class. All that I have in my class:

let stb = UIStoryboard(name: "Walkthrough", bundle: nil) let walkthrough = stb.instantiateViewControllerWithIdentifier("walk") as! BWWalkthroughViewController self.presentViewController(walkthrough, animated: true, completion: nil) 

I want to apply the following custom segue:

 class CustomSegue: UIStoryboardSegue { override func perform() { // Assign the source and destination views to local variables. var firstVCView = self.sourceViewController.view as UIView! var secondVCView = self.destinationViewController.view as UIView! // Get the screen width and height. let screenWidth = UIScreen.mainScreen().bounds.size.width let screenHeight = UIScreen.mainScreen().bounds.size.height // Specify the initial position of the destination view. secondVCView.frame = CGRectMake(0.0, screenHeight, screenWidth, screenHeight) // Access the app key window and insert the destination view above the current (source) one. let window = UIApplication.sharedApplication().keyWindow window?.insertSubview(secondVCView, aboveSubview: firstVCView) // Animate the transition. UIView.animateWithDuration(0.2, animations: { () -> Void in firstVCView.frame = CGRectOffset(firstVCView.frame, -screenWidth, 0.0) secondVCView.frame = CGRectOffset(secondVCView.frame, -screenWidth, 0.0) }) { (Finished) -> Void in self.sourceViewController.presentViewController(self.destinationViewController as! UIViewController, animated: false, completion:nil) } } } 

I can not get it to work with any pointers, please?

+5
source share
1 answer

While the first answer should be "using Storyboard Segues", you can solve custom transitions as follows:

General approach

  • Modify CustomSegue to accept both UIStoryboardSegue and UIViewControllerAnimatedTransitioning .
  • Refactor CustomSegue so that animations can be used by both protocols.
  • Configure a delegate to a navigation controller, which can be itself, to provide custom transitions to push and pop
  • let animationControllerForOperation create and return a CustomSegue instance with an identifier of your choice.

Overview

 // Adopt both protocols class CustomSegue: UIStoryboardSegue, UIViewControllerAnimatedTransitioning { func animate(firstVCView:UIView, secondVCView:UIView, containerView:UIView, transitionContext: UIViewControllerContextTransitioning?) { // factored transition code goes here }) { (Finished) -> Void in if let context = transitionContext { // UIViewControllerAnimatedTransitioning } else { // UIStoryboardSegue } } } func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { // return timing } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { // Perform animate using transitionContext information // (UIViewControllerAnimatedTransitioning) } override func perform() { // Perform animate using segue (self) variables // (UIStoryboardSegue) } } 

The following is a complete code example. It has been tested. Please note that I also fixed some animation errors from the original question and added a gradual zoom effect to emphasize the animation.


CustomSegue Class

 // Animation for both a Segue and a Transition class CustomSegue: UIStoryboardSegue, UIViewControllerAnimatedTransitioning { func animate(firstVCView:UIView, secondVCView:UIView, containerView:UIView, transitionContext: UIViewControllerContextTransitioning?) { // Get the screen width and height. let offset = secondVCView.bounds.width // Specify the initial position of the destination view. secondVCView.frame = CGRectOffset(secondVCView.frame, offset, 0.0) firstVCView.superview!.addSubview(secondVCView) secondVCView.alpha = 0; // Animate the transition. UIView.animateWithDuration(self.transitionDuration(transitionContext!), animations: { () -> Void in firstVCView.frame = CGRectOffset(firstVCView.frame, -offset, 0.0) secondVCView.frame = CGRectOffset(secondVCView.frame, -offset, 0.0) secondVCView.alpha = 1; // emphasis }) { (Finished) -> Void in if let context = transitionContext { context.completeTransition(!context.transitionWasCancelled()) } else { self.sourceViewController.presentViewController( self.destinationViewController as! UIViewController, animated: false, completion:nil) } } } func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { return 4 // four seconds } // Perform Transition (UIViewControllerAnimatedTransitioning) func animateTransition(transitionContext: UIViewControllerContextTransitioning) { self.animate(transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!.view, secondVCView: transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!.view, containerView: transitionContext.containerView(), transitionContext: transitionContext) } // Perform Segue (UIStoryboardSegue) override func perform() { self.animate(self.sourceViewController.view!!, secondVCView: self.destinationViewController.view!!, containerView: self.sourceViewController.view!!.superview!, transitionContext:nil) } } 

Host ViewController Class

 class ViewController: UIViewController, UINavigationControllerDelegate { override func viewDidLoad() { super.viewDidLoad() self.navigationController?.delegate = self } func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { switch operation { case .Push: return CustomSegue(identifier: "Abc", source: fromVC, destination: toVC) default: return nil } } } 
+5
source

All Articles