11

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.

Krumelur
  • 32,180
  • 27
  • 124
  • 263

4 Answers4

24

@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.

Jon
  • 7,848
  • 1
  • 40
  • 41
  • I'm guessing `TransitionAnimator` is the UIViewControllerAnimatedTransitioning class. And I'm guessing he added the property `presenting` to it. – Mark Moeykens Dec 23 '18 at 02:04
4

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 (https://i.stack.imgur.com/6Tc7a.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.

rounak
  • 9,217
  • 3
  • 42
  • 59
  • Can you share the animator code, I'm working on similar thing as shown in the image. – anuraagdjain Feb 10 '17 at 09:07
  • I've give CGAffineTransform(translationX: 1.02, y: 1.02) during push and during pop (0.01,0.01) seems to be working fine, would like to know what's your value too :) – anuraagdjain Feb 10 '17 at 09:56
2

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

Patrik Vaberer
  • 646
  • 6
  • 15
1

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];
}
Binary Pulsar
  • 1,209
  • 10
  • 17