Blurred Transparent Modal Segues

How to create depth with animated blurred layers

Richard Mullinix
iOS Development

--

https://github.com/edwurtle/BlurredSegues

With iOS 7, have you ever wished for the following?

self.view.backgroundColor = [UIColor transparentBlur];

Apple does not provide such a method. In fact Apple doesn’t provide any built in method for creating blurred transparent layers. Supposedly, Apple accesses the hardware directly to render their own blurred layers. However due to security concerns, they do not provide developers access to that method. So how do we add animated blurred layers and depth to our apps? Or at very least, how do we fake it? How can we do the following:

Example Blurred Transparent Segue

Creating a Blurred Image

WWDC 2013 Implementing Engaging UI on iOS (Session 226) at 15:05 gives us a great starting point. It’s simple to create a blurred image of any view with UIImage+ImageEffects. There are many blur methods available: light effect, extra light effect, dark effect and color tint effects. Here’s code to create a blurred image of any view.

// create image of a viewCGFloat scale = [[UIScreen mainScreen] scale];UIGraphicsBeginImageContextWithOptions(view.frame.size, YES, scale);[view drawViewHierarchyInRect:view.frame afterScreenUpdates:NO];UIImage *image = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();// create dark blurred image, requires UIImage+ImageEffectsUIImage *blurredImage = [image applyDarkEffect];

Simply place the blurred image into the background of the overlaying view and the depth effect is almost complete. But it’s just a static blurred image!

Blurred image with dark effect as the background.

Standard Modal Segue

Let’s animate the blurred layer from the bottom of screen. First let’s try a standard modal segue and set the blurred background image in prepareForSegue method. The results are below and the results are ugly. The blurred background doesn’t keep in sync with the real background and entire layered effect is ruined.

left side: standard modal segue / right side: desired effect

Custom Modal Segue with Blurred Background

In order to keep the blurred background in sync with the real background a custom transition or custom segue is required. This article details a custom segue, however the same idea can be applied to a custom view controller transition. The main approach: The background blurred image needs to stay still relative to the parent view and the background blur image needs to be “revealed” as the modal view animates into place.

Custom Segue Basics

Custom segues can be used in code or directly inside storyboard. In order to create a custom segue just create a subclass of UIStoryboardSegue and implement the perform method. The perform method handles the animation from source view controller to destination view controller. Here’s a great blog written by Phillipus all about custom segues and rewind segues. The rest of the article details a specific custom segue designed for blurred backgrounds.

Blurred Background Segue

Now the specifics for our custom segue. Keep in mind the main approach:

The background blurred image needs to stay still relative to the parent view and the background blur image needs to be “revealed” as the modal view animates into place.

I’ll be going over code that is inside the perform method of your custom segue. This segue will animate the view from the bottom of the screen and keep the blurred background correctly in sync with the real background.

The first step: clear the background of destination view. We want to keep it clear and without any background image until the animation is complete. The animated blurred background will be placed underneath the destination view.

UIViewController *sourceViewController = self.sourceViewController;UIViewController *destinationViewController = self.destinationViewController;UIView *sourceView = sourceViewController.view;UIView *destinationView = destinationViewController.view;destinationView.backgroundColor = [UIColor clearColor];

The second step: setup a blurred image view. Create a image view with a ZERO height frame positioned on the bottom(y = source view’s height). In the fourth step we will animate the frame from zero height to full height. With image view mode set to UIViewContentModeBottom and clipsToBounds = YES, the image will gradually be revealed and stay positioned along the bottom without distortion. Now create the blurred image and set the blurred image view’s image. Finally add the blurred image view to source view.

UIImageView *blurredImageView = [[UIImageView alloc] initWithFrame: CGRectMake(0.0, sourceView.frame.size.height, sourceView.frame.size.width, 0.0)];blurredImageView.clipsToBounds = YES;blurredImageView.contentMode = UIViewContentModeBottom;UIGraphicsBeginImageContextWithOptions(view.frame.size, YES, [[UIScreen mainScreen] scale]);[sourceView drawViewHierarchyInRect:sourceView.frame) afterScreenUpdates:NO];UIImage *sourceViewImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();UIImage *blurredImage = [sourceViewImage applyDarkEffect];blurredImageView.image = blurredSourceImage;[sourceView addSubview:blurredImageView];

The third step: set the destination view off screen and below it’s final location and add destination view to source view.

CGPoint destinationCenter = destinationView.center;destinationView.center = CGPointMake(destinationCenter.x, destinationCenter.y+destinationView.frame.size.height);[sourceView addSubview:destinationView];

The fourth step: perform the animation and clean up. Animate the destination view to its final location and animate the blurred image view’s frame to the full frame size. At the completion of animation, remove the blurred image view and destination view from the source view, insert the blurred image view at the bottom of the destination view and present the destination view controller without animation.

[UIView animateWithDuration:0.6 delay:0.0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseIn animations:^{destinationView.center = destinationCenter;blurredImageView.frame = sourceView.frame;}completion:^(BOOL finished){[blurredImageView removeFromSuperview];[destinationView removeFromSuperview];[destinationView insertSubview:blurredImageView atIndex:0];[sourceViewController presentViewController:destinationViewController animated:NO completion:NULL]; }];

Blurred Background Unwind Segue

We are almost done. There still needs to be an “unwind” segue to reverse the animation. The rewind segue perform method is the opposite of the previous segue. I’m not going into to the details here, you can see the custom unwind segue in the example project. Keep in mind unwind segues require a bit of extra setup in storyboard and source view controller. Refer again to Phillipus’s blog for details about unwind segues and my example project for blurred unwind segue.

Where to go from here?

This segue animate up from the bottom of the screen. You can extend this approach to many other transitions: mimic the notification center (from the top) or create a sidebar (from left or right). The main approach still applies:

The background blurred image needs to stay still relative to the parent view and the background blur image needs to be “revealed” as the modal view animates into place.

Keep in mind, this is just a visual “trick”. The background image is still static and any changes to views underneath will go unnoticed.

--

--