Presenting a UIViewController modally, with custom animations

Pedro Mancheno
Lifesum: Healthy living, simplified.
2 min readFeb 16, 2016

Designers at Lifesum love to create beautiful UI and in order to keep up with their demands, the iOS Developers on the team try to build reusable tools to make their dreams come true.

When trying to accomplish the seemingly easy task to present a view controller with a transparent background modally, using a fade in animation there are several valid approaches.

I decided to create my own object called CustomPresentationController to handle this kind of presentation. Internally, this controller uses animation transitioning delegation, an API available starting with iOS 7.

This presentation controller has a simple method which sets the presentation style for the view controller we want to present, it sets itself as the transitioning delegate and then performs the usual modal presentation as you would expect:

- (void)presentViewController:(UIViewController *)viewController
fromViewController:(UIViewController *)presentingViewController
presentationAnimation:(CustomPresentationAnimation)animation
{
self.animation = animation;
viewController.modalPresentationStyle = UIModalPresentationCustom;
viewController.transitioningDelegate = self;
viewController.modalPresentationCapturesStatusBarAppearance = YES;
[viewController setNeedsStatusBarAppearanceUpdate];

if ([presentingViewController.presentedViewController isKindOfClass:viewController.class]) {
return;
}
[presentingViewController presentViewController:viewController animated:YES completion:nil];
}

It’s important to set the modalPresentationCapturesStatusBarAppearance property to YES and force the status bar appearance to update, if your presented view controller has a different preferredStatusBarStyle.

The CustomPresentationController has a property to keep track of it’s state which is then updated in the UIViewControllerTransitioningDelegate methods:

@property (assign, nonatomic) isPresenting/*
...
*/
- (id)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source
{
self.isPresenting = YES;
return self;
}
- (id)animationControllerForDismissedController:(UIViewController *)dismissed
{
self.isPresenting = NO;
return self;
}

The real magic takes place in the UIViewControllerAnimatedTransitioning methods, where we will handle the actual transition, giving it the duration and style we desire.

- (NSTimeInterval)transitionDuration:(id)transitionContext
{
return 0.25;
}
- (void)animateTransition:(id)transitionContext
{
UIViewController* firstVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController* secondVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView* containerView = [transitionContext containerView];
UIView* firstView = firstVC.view;
UIView* secondView = secondVC.view;
if (self.isPresenting) {
[containerView addSubview:secondView];
secondView.frame = (CGRect){
containerView.frame.origin.x,
containerView.frame.origin.y + containerView.frame.size.height,
containerView.frame.size
};
firstView.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
[UIView animateWithDuration:0.25 animations:^{
secondView.frame = containerView.frame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
} else {
[UIView animateWithDuration:0.25 animations:^{
firstView.frame = (CGRect){
containerView.frame.origin.x,
containerView.frame.origin.y + containerView.frame.size.height,
containerView.frame.size
};
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
}

This code performs a slide-in-from-the-bottom animation mimicking the default modal animation. You can further extend this class to create crazier transitions.

The important thing is that the presenting view controller’s view will always remain in the back and if your presented view controller sets a semi transparent background you will get a very stylish effect.

You can find the entire implementation here:

This solution works for iOS 7+

--

--

Pedro Mancheno
Lifesum: Healthy living, simplified.

Software Engineer. Crafting beautiful code for the sake of my future self.