Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use UIViewControllerAnimatedTransitioning with UINavigationController?

How can I get custom transitions (iOS7) when pushing a view controller onto UINavigationController? I tried setting the TransitioningDelegate both in the UINavigationController and also on the controller I'm pushing The methods never get called.

All examples I find use custom transitions when presenting modally.

like image 434
Krumelur Avatar asked Apr 05 '14 17:04

Krumelur


4 Answers

@rounak has the right idea, but sometimes it helps to have code ready without having to download from github.

Here are the steps that I took:

  1. Make your FromViewController.m conform to UINavigationControllerDelegate. Other sample code out there tells you to conform to UIViewControllerTransitioningDelegate, but that's only if you're presenting the ToViewController.

    @interface ViewController : UIViewController

  2. Return your custom transition animator object in the delegate callback method in FromViewController:

    - (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                   animationControllerForOperation:(UINavigationControllerOperation)operation
                                                fromViewController:(UIViewController *)fromVC
                                                  toViewController:(UIViewController *)toVC {
        TransitionAnimator *animator = [TransitionAnimator new];
        animator.presenting = (operation == UINavigationControllerOperationPush);
        return animator;
    }
    
  3. Create your custom animator class and paste these sample methods:

    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
        return 0.5f;
        }
    
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext     {
    // Grab the from and to view controllers from the context
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    // Set our ending frame. We'll modify this later if we have to
    CGRect endFrame = CGRectMake(80, 280, 160, 100);
    
    if (self.presenting) {
        fromViewController.view.userInteractionEnabled = NO;
    
        [transitionContext.containerView addSubview:fromViewController.view];
        [transitionContext.containerView addSubview:toViewController.view];
    
        CGRect startFrame = endFrame;
        startFrame.origin.x += 320;
    
        toViewController.view.frame = startFrame;
    
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            fromViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
            toViewController.view.frame = endFrame;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
    else {
        toViewController.view.userInteractionEnabled = YES;
    
        [transitionContext.containerView addSubview:toViewController.view];
        [transitionContext.containerView addSubview:fromViewController.view];
    
        endFrame.origin.x += 320;
    
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            toViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic;
            fromViewController.view.frame = endFrame;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
    }
    

Essentially, the animator is the object doing the heavy lifting. Of course, you can make your UINavigationControllerDelegate be a separate object, but that depends on how your architect your app.

like image 158
Jon Avatar answered Nov 20 '22 12:11

Jon


objc.io's post on view controller transitions are specifically for pushing and popping view controllers. http://objc.io/issue-5/view-controller-transitions.html

I've done this animation (http://i.imgur.com/1qEyMu3.gif) solely based on the objc.io post.

In short you have to have a class(es) implementing UINavigationControllerDelegate, and UIViewControllerAnimatedTransitioning with the required methods for returning the correct animator, and performing the animations.

like image 37
rounak Avatar answered Nov 20 '22 12:11

rounak


You can look at my demo project which demonstrates using custom transitions in UINavigationController. Look at https://github.com/Vaberer/BlurTransition.

like image 32
Patrik Vaberer Avatar answered Nov 20 '22 13:11

Patrik Vaberer


EDIT: Just realised this might not answer your question. But it is an alternative.

If you're using a storyboard you can do a custom transition by creating a custom segue. In the attributes inspector change the segue class name to your custom transition class e.g. MySegue. Then create the MySegue class and implement the -(void)perform method to perform your transition.

- (void) perform{
      UIViewController *source = self.sourceViewController;
      UIViewController *destination = self.destinationViewController;
      [UIView transitionFromView:source.view
                          toView:destination.view
                        duration:0.50f
                         options:UIViewAnimationOptionTransitionFlipFromTop
                      completion:nil];
}
like image 1
Pulsar Avatar answered Nov 20 '22 14:11

Pulsar