Swift explanation ------------ custom UINavigationController push and pop animation,

Source: Internet
Author: User

Swift explanation ------------ custom UINavigationController push and pop animation,
Customize the push and pop animation of UINavigationController

Create a simple project, drag a navigation controller in the storyboard, and change rootViewController to our ViewController.

To implement Custom Animation switching, we need to implement two protocols.UIViewControllerAnimatedTransitioning,UINavigationControllerDelegate

The UIViewControllerAnimatedTransitioning Protocol aims to focus on the implementation of the animation, while using custom animations without affecting other attributes of the view, then, you can write Custom Animation code in the callback of this Protocol to switch the specific content. Any object implementing this Protocol is called an animation controller.

There are two important methods:

transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeIntervalanimateTransition(transitionContext: UIViewControllerContextTransitioning)

The first one returns the duration of an animation, and the second is the animation body.transitionContextHere is a core. This object can be used to obtain context information during the switchover, for example, from which VC to which VC.

Let toViewController = transitionContext. viewControllerForKey (response); // let fromViewController = transitionContext. viewControllerForKey (response); let container = transitionContext. containerView () container !. AddSubview (toViewController ?. View )!); If response = UINavigationControllerOperation. Push {toViewController ?. View. layer. anchorPoint = CGPointMake (0, 0) toViewController ?. View. center = CGPointMake (0, 0) toViewController ?. View. transform = CGAffineTransformMakeRotation (CGFloat (-M_PI_2) UIView. animateWithDuration (self. transitionDuration (transitionContext), delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.7, options: UIViewAnimationOptions. allowUserInteraction, animations: {()-> Void in toViewController ?. View. transform = CGAffineTransformMakeRotation (0)}, completion: {(B)-> Void in toViewController ?. View. transform = CGAffineTransformIdentity // The animation is completed. // if the execution is canceled, the transitionContext. completeTransition (! TransitionContext. transitionWasCancelled ()} else if response = UINavigationControllerOperation. Pop {toViewController ?. View. layer. anchorPoint = CGPointMake (1, 0) // Do not be stupid between 0 and 1 .. ToViewController ?. View. center = CGPointMake (toViewController !. View. bounds. width, 0) toViewController ?. View. transform = CGAffineTransformMakeRotation (CGFloat (-M_PI_2 * 3) UIView. animateKeyframesWithDuration (1.3, delay: 0, options: UIViewKeyframeAnimationOptions. allowUserInteraction, animations: {()-> Void in UIView. addKeyframeWithRelativeStartTime (0.0, relativeDuration: 0.4, animations: {()-> Void in toViewController ?. View. transform = convert (CGFloat (-M_PI_2) * 4)}) UIView. addKeyframeWithRelativeStartTime (0.4, relativeDuration: 0.2, animations: {()-> Void in toViewController ?. View. transform = convert (CGFloat (M_PI_2/10)}) UIView. addKeyframeWithRelativeStartTime (0.6, relativeDuration: 0.3, animations: {()-> Void in toViewController ?. View. transform = CGAffineTransformMakeRotation (CGFloat (-M_PI_2) * 4)}, completion: {(B)-> Void in toViewController ?. View. transform = CGAffineTransformIdentity print (transitionContext. transitionWasCancelled () // The animation is completed // if the execution is canceled, the transitionContext. completeTransition (! TransitionContext. transitionWasCancelled ())})}

Here is a piece of code I wrote. Of course I have divided it into pop and push,operVariables are obtained from another method. To and from have nothing to say,containerThis is a special container, and the animation during switching will be carried out in this container. Others are push and pop. I made an animation subject myself. Of course, you can change these parts as needed. Here we will mainly talk about customization, not animation.

We also need to implement another protocol.UINavigationControllerDelegateThis protocol is used to configure the interaction mode of some navigation controllers.

Define in our classvar navgationController:UINavigationController

During initialization

  init(nav:UINavigationController){        self.navgationController = nav        super.init()        self.navgationController.delegate = self    }
 func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {        oper = operation        return self    }

The aboveoperThis is from here. We can see whether push or pop is currently in progress.return nilThe default animation is used,return selfIt means we can use our own settings. If you only define one push or pop, you can add a judgment.
At this time, the effect should be as follows:

Gif is a bit choppy. It should all have a bullet effect... The source code will be provided later. You can run it yourself.

If you want to add this method to support gestures

Func navigationController (navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning)-> UIViewControllerInteractiveTransitioning? {/*** Monitoring progress */if animationController. isKindOfClass (MyAnimation. self) {return self. _ interactivePushTransition} return nil ;}

Then, write two gesture operations for push and pop respectively.

Func handleControllerPush (sender: UIPanGestureRecognizer) {let location = sender. translationInView (sender. view) var progress = location. x/(sender. view ?. Bounds. size. width )! // Print ("\ (location. x), \ (sender. view ?. Bounds. size. width )!) ") Progress = max (-1, min (progress, 0); let pz = progress *-1 // print (progress) if sender. state = UIGestureRecognizerState. start with the an {/*** gesture to create a new Monitored object */self. _ interactivePushTransition = UIPercentDrivenInteractiveTransition ()/*** tells the Controller to start executing the push animation */self. navgationController. pushViewController (toVc !, Animated: true)} else if sender. state = UIGestureRecognizerState. Changed {/*** update the progress of the gesture * // print (progress *-1) _ interactivePushTransition ?. UpdateInteractiveTransition (pz)} else if (sender. state = UIGestureRecognizerState. ended | sender. state = UIGestureRecognizerState. changed) {/*** if the progress is greater than half at the end of the gesture, the push operation is completed; otherwise, the operation is resumed. */Print (pz) if (pz> 0.14) {self. _ interactivePushTransition ?. FinishInteractiveTransition ()} else {self. _ interactivePushTransition ?. CancelInteractiveTransition ()} // it is important to set interactionController to nil when the animation switching is complete. If the next animation is non-interactive, we do not want to get a strange interactionController self. _ interactivePushTransition = nil }}

Pop won't be released. Download the code by yourself ..

Write your own navigation controller.

protocol MyPushNav{    func pushView()->UIViewController;}class MyNavigationController: UINavigationController {    var pushDele:MyPushNav?    var animate:MyAnimation?    override func viewDidLoad() {        super.viewDidLoad()        animate = MyAnimation(nav: self);        let pan = UIPanGestureRecognizer(target: animate, action: "handleControllerPop:")        self.view.addGestureRecognizer(pan)    }    override func viewDidAppear(animated: Bool) {         pushView();    }    func pushView(){        let pan2 = UIPanGestureRecognizer(target: animate, action: "handleControllerPush:")        if let _ = pushDele {            let sc = pushDele?.pushView()            self.animate?.toVc = sc            (pushDele as! UIViewController).view.addGestureRecognizer(pan2)        }else{            self.view.removeGestureRecognizer(pan2)        }    }}

If push is required, we must tell which push is used, so the protocol is used.
Pop does not require any operation.

class ViewController: UIViewController,MyPushNav {       override func viewDidLoad() {        super.viewDidLoad()        (self.navigationController as! MyNavigationController).pushDele = self        // Do any additional setup after loading the view, typically from a nib.    }    override func didReceiveMemoryWarning() {        super.didReceiveMemoryWarning()        // Dispose of any resources that can be recreated.    }    func pushView()->UIViewController {        return SecondViewController()    }}

This is push ..

Attached a useful graph for understanding

Source Code address: MyNavigationController

Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.