iOS 7 Translucent Modal View Controller

IosObjective CUinavigationcontrollerIos7Presentmodalviewcontroller

Ios Problem Overview


The App Store app on iOS 7 uses a frosted glass-type effect where it is possible to see the view behind. Is this using an API built into iOS 7 or is it custom code. I was hoping it would be the former but I can't see any obvious references in the documentation. Obvious things like (like setting the alpha property on the modal view) don't seem to have any effect.

To see an example, open the App Store app and press the button at the top-right.

App Store home page Modal view in the App Store

Ios Solutions


Solution 1 - Ios

With the release of iOS 8.0, there is no need for getting an image and blurring it anymore. As Andrew Plummer pointed out, you can use UIVisualEffectView with UIBlurEffect.

UIViewController * contributeViewController = [[UIViewController alloc] init];
UIBlurEffect * blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *beView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
beView.frame = self.view.bounds;

contributeViewController.view.frame = self.view.bounds;
contributeViewController.view.backgroundColor = [UIColor clearColor];
[contributeViewController.view insertSubview:beView atIndex:0];
contributeViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;

[self presentViewController:contributeViewController animated:YES completion:nil];

Solution that works before iOS 8

I would like to extend on rckoenes' answer:

As emphasised, you can create this effect by:

  1. Convert the underlying UIView to an UIImage
  2. Blur the UIImage
  3. Set the UIImage as background of your view.

enter image description here


Sounds like a lot of work, but is actually done pretty straight-forward:

1. Create a category of UIView and add the following method:

-(UIImage *)convertViewToImage
{
    UIGraphicsBeginImageContext(self.bounds.size);
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
 
    return image;
}

2. Make an image of the current view and blur it by using Apple's Image Effect category (download)

UIImage* imageOfUnderlyingView = [self.view convertViewToImage];
imageOfUnderlyingView = [imageOfUnderlyingView applyBlurWithRadius:20
                             tintColor:[UIColor colorWithWhite:1.0 alpha:0.2]
                 saturationDeltaFactor:1.3
                             maskImage:nil];

3. Set it as background of your overlay.

-(void)viewDidLoad
{
   self.view.backgroundColor = [UIColor clearColor];
   UIImageView* backView = [[UIImageView alloc] initWithFrame:self.view.frame];
   backView.image = imageOfUnderlyingView;
   backView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
   [self.view addSubview:backView];
}

Solution 2 - Ios

Just reimplemented Sebastian Hojas' solution in Swift:

1. Create a UIView extension and add the following method:

extension UIView {
    func convertViewToImage() -> UIImage{
        UIGraphicsBeginImageContext(self.bounds.size);
        self.drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext();
    
        return image;
    }
}

2. Make an image of the current view and blur it by using Apple's Image Effect (I found a reimplementation of this in Swift here: SwiftUIImageEffects

var imageOfUnderlyingView = self.view.convertViewToImage()
imageOfUnderlyingView = imageOfUnderlyingView.applyBlurWithRadius(2, tintColor: UIColor(white: 0.0, alpha: 0.5), saturationDeltaFactor: 1.0, maskImage: nil)!

3. Set it as background of your overlay.

let backView = UIImageView(frame: self.view.frame)
backView.image = imageOfUnderlyingView
backView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.5)
view.addSubview(backView)

Solution 3 - Ios

I think this is the easiest solution for a modal view controller that overlays everything with a nice blur (iOS8)

    UIViewController * contributeViewController = [[UIViewController alloc] init];
    
    UIBlurEffect * blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
    UIVisualEffectView *beView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    beView.frame = self.view.bounds;
    
    contributeViewController.view.frame = self.view.bounds;
    contributeViewController.view.backgroundColor = [UIColor clearColor];
    [contributeViewController.view insertSubview:beView atIndex:0];
    contributeViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
    
    [self presentViewController:contributeViewController animated:YES completion:nil];

Solution 4 - Ios

There is no API available in the iOS 7 SDK which will allow you to "frost" the underlaying view controller.

What I have done is render the underlaying view to an image, which I then frosted and set that as background the the view that is being presented.

Apple provides a good example for this: https://developer.apple.com/downloads/index.action?name=WWDC%202013

The project you want is called, iOS_RunningWithASnap

Solution 5 - Ios

A little simplier way to achieve this (based on Andrew Plummer's answer) with Interface Builder (also it removes side effect that appears in Andrews answer):

  • In IB add Visual Effect View to your View Controller under your other views;
  • Make top, bottom, left, right constraints from Visual Effect View to top (parent) View, set all of them to 0;
  • Set Blur Style;
  • Add the code where you present your new fancy View Controller:

UIViewController *fancyViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"yourStoryboardIDFOrViewController"];

fancyViewController.view.backgroundColor = [UIColor clearColor];
fancyViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;

[self presentViewController:fancyViewController
                   animated:YES
                 completion:nil];

Actually, the second and third lines are VERY important - otherwise controller will blink and then turn black.

Solution 6 - Ios

Since iOS 8, this works:

        let vc = UIViewController()
        vc.view = UIVisualEffectView(effect: UIBlurEffect(style: .Light))
        vc.modalPresentationStyle = .OverFullScreen

        let nc = UINavigationController(rootViewController: vc)
        nc.modalPresentationStyle = .OverFullScreen

        presentViewController(nc, animated: true, completion: nil)

The key is the .OverFullScreen flag and ensuring the viewControllers have a blur UIVisualEffectView that is the first visible view.

Solution 7 - Ios

As @rckoenes said, there is no Apple provided framework to get that effect. But some people out there already built good alternatives, like this one for example:

https://github.com/JagCesar/iOS-blur/

Solution 8 - Ios

A couple of alternative approaches that also work on iOS 5 and 6:

FXBlurView: https://github.com/nicklockwood/FXBlurView

iOS RealtimeBlur: https://github.com/alexdrone/ios-realtimeblur

Solution 9 - Ios

Fast & easy solution with XIB support you can use for the old school boys https://github.com/cezarywojcik/CWPopup

Solution 10 - Ios

Instead of presenting the viewController as a modalView, you could add it as a child viewController and create a custom animation. You would then only need to change the default view of the viewController to a UIToolBar in viewDidLoad.

This will allow you to mimic the appstore's blurred modal view as closely as possible.

Solution 11 - Ios

I have uploaded my take of the blurred view controller to [GitHub][1]. It also comes with a segue subclass so you can use it in your storyboards.

Repository: https://github.com/datinc/DATBlurSegue

Solution 12 - Ios

Apple released the UIImageEffect category for those effects. Those category should be added manually to the project, and it support iOS7.

Solution 13 - Ios

You can use UIToolbar as background. By default UIToolbar have 50px height. Add auto layout constraints on UIToolbar. Then select height constraint and modify it.

Hierarchy will look like this:

UIView -> clear colour for background.
- UIToolbar
- Other contents.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIanView Question on Stackoverflow
Solution 1 - IosSebastian HojasView Answer on Stackoverflow
Solution 2 - IosjuliensaadView Answer on Stackoverflow
Solution 3 - IosAndrew PlummerView Answer on Stackoverflow
Solution 4 - IosrckoenesView Answer on Stackoverflow
Solution 5 - IosAndrei KonstantinovView Answer on Stackoverflow
Solution 6 - IosmxclView Answer on Stackoverflow
Solution 7 - IosJörg KirchhofView Answer on Stackoverflow
Solution 8 - IosiwasrobbedView Answer on Stackoverflow
Solution 9 - IosAtefView Answer on Stackoverflow
Solution 10 - IosVadoffView Answer on Stackoverflow
Solution 11 - IosdatincView Answer on Stackoverflow
Solution 12 - IosYedidya ReissView Answer on Stackoverflow
Solution 13 - IosRam SutharView Answer on Stackoverflow