Sunday, March 4, 2012

Custom Transition Animation for Modal View Controllers

Needed to implement a custom animation (push from right/left when presenting a modal view controller, and then pushing out to the other direction when dismissing the dialog).
Yosi found this snippet: http://blog.radi.ws/post/5924267283/custom-modal-uiviewcontroller-transitions
by Evadne Wu. This was so cool, and I think I made it a bit more fun by creating a UIViewController category to do that (I was a bit lazy, so I only implemented the Push in/out transition, but this can be easily extended):


//
//  UIViewController+Transitions.h
//  Labgoo Misc
//
//  Created by Israel Roth on 3/4/12.
//  Copyright (c) 2012 Labgoo LTD. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIViewController(Transitions)

- (void) presentModalViewController:(UIViewController *)modalViewController withPushDirection: (NSString *) direction;
- (void) dismissModalViewControllerWithPushDirection:(NSString *) direction;

@end


and the implementation:

//
//  UiViewController+Transitions.m
//  Labgoo Misc
//
//  Created by Israel Roth on 3/4/12.
//  Copyright (c) 2012 Labgoo LTD. All rights reserved.
//

#import "UIViewController+Transitions.h"

@implementation UIViewController(Transitions)

- (void) presentModalViewController:(UIViewController *)modalViewController withPushDirection: (NSString *) direction {

    [CATransaction begin];
    
    CATransition *transition = [CATransition animation];
    transition.type = kCATransitionPush;
    transition.subtype = direction;
    transition.duration = 0.25f;
    transition.fillMode = kCAFillModeForwards;
    transition.removedOnCompletion = YES;
    
    [[UIApplication sharedApplication].keyWindow.layer addAnimation:transition forKey:@"transition"];        
    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
    [CATransaction setCompletionBlock: ^ {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(transition.duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^ {
            [[UIApplication sharedApplication] endIgnoringInteractionEvents];        
        });
    }];
    
    [self presentModalViewController:modalViewController animated:NO];
    
    [CATransaction commit];

}

- (void) dismissModalViewControllerWithPushDirection:(NSString *) direction {

    [CATransaction begin];
    
    CATransition *transition = [CATransition animation];
    transition.type = kCATransitionPush;
    transition.subtype = direction;
    transition.duration = 0.25f;
    transition.fillMode = kCAFillModeForwards;
    transition.removedOnCompletion = YES;

    [[UIApplication sharedApplication].keyWindow.layer addAnimation:transition forKey:@"transition"];        
    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
    [CATransaction setCompletionBlock: ^ {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(transition.duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^ {
            [[UIApplication sharedApplication] endIgnoringInteractionEvents];        
        });
    }];
    
    [self dismissModalViewControllerAnimated:NO];
    
    [CATransaction commit];
    
}

@end



to use it, you import "UIViewController+Transitions.h" in your file and call the presentModalViewController:withPushDirection:
the direction parameter receives core animation transition sub-types such as kCATransitionFromRight

Enjoy...




And a message from our advertisers:


Toptal provides remote engineers and designers of high quality. I recommend them. Follow this link (full disclosure: this is my affiliate link):
https://www.toptal.com/#engage-honest-computer-engineers-today