iOS: Modal ViewController with transparent background

175,508

Solution 1

This following code only works on the iPad.

self.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:modalVC animated:YES];

I would go with adding a sub view.

Here is a very good discussion. Look at the comments specifically. Not only the answer.

Modal View

If I were you I wouldn't do it. I would add a sub view and do it. It seems to give me a better control over things.

EDIT:

As mentioned by Paul Linsay, since iOS 8 all that's needed is UIModalPresentationOverFullScreen for the modalPresentationStyle of the ViewController being presented. This would also cover of navigationBar and tabBar buttons.

Solution 2

For those trying to get this to work in iOS 8, the "Apple-approved" way to display a transparent modal view controller is by setting modalPresentationStyle on the presented controller to UIModalPresentationOverCurrentContext.

This can be done in code, or by setting the properties of the segue in the storyboard.

From the UIViewController documentation:

UIModalPresentationOverCurrentContext

A presentation style where the content is displayed over only the parent view controller’s content. The views beneath the presented content are not removed from the view hierarchy when the presentation finishes. So if the presented view controller does not fill the screen with opaque content, the underlying content shows through.

When presenting a view controller in a popover, this presentation style is supported only if the transition style is UIModalTransitionStyleCoverVertical. Attempting to use a different transition style triggers an exception. However, you may use other transition styles (except the partial curl transition) if the parent view controller is not in a popover.

Available in iOS 8.0 and later.

https://developer.apple.com/documentation/uikit/uiviewcontroller

The 'View Controller Advancements in iOS 8' video from WWDC 2014 goes into this in some detail.

Note:

  • Be sure to give your presented view controller a clear background color, lest it not actually be see-through!
  • You have to set this before presenting ie setting this parameter in the viewDidLoad of the presentedViewController won't have any affect

Solution 3

In iOS 8.0 and above it can be done by setting the property modalPresentationStyle to UIModalPresentationOverCurrentContext

//Set property **definesPresentationContext** YES to avoid presenting over presenting-viewController's navigation bar

self.definesPresentationContext = YES; //self is presenting view controller
presentedController.view.backgroundColor = [YOUR_COLOR with alpha OR clearColor]
presentedController.modalPresentationStyle = UIModalPresentationOverCurrentContext;

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

See Image Attached

Solution 4

This code works fine on iPhone under iOS6 and iOS7:

presentedVC.view.backgroundColor = YOUR_COLOR; // can be with 'alpha'
presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:presentedVC animated:YES completion:NULL];

In this case you miss slide-on animation. To retain animation you still can use the following "non-elegant" extension:

[presentingVC presentViewController:presentedVC animated:YES completion:^{
    [presentedVC dismissViewControllerAnimated:NO completion:^{
        presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
        [presentingVC presentViewController:presentedVC animated:NO completion:NULL];
    }];
}];

If our presentingV is located inside of UINavigationController or UITabbarController you need to operate with that controllers as presentingVC.

Further, in iOS7 you can implement custom transition animation applying UIViewControllerTransitioningDelegate protocol. Of course, in this case you can get transparent background

@interface ModalViewController : UIViewController <UIViewControllerTransitioningDelegate>

First, before presenting you have to set modalPresentationStyle

modalViewController.modalPresentationStyle = UIModalPresentationCustom;

Then you have to implement two protocol methods

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    CustomAnimatedTransitioning *transitioning = [CustomAnimatedTransitioning new];
    transitioning.presenting = YES;
    return transitioning;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    CustomAnimatedTransitioning * transitioning = [CustomAnimatedTransitioning new];
    transitioning.presenting = NO;
    return transitioning;
}

The last thing is to define your custom transition in CustomAnimatedTransitioning class

@interface CustomAnimatedTransitioning : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic) BOOL presenting;
@end

@implementation CurrentContextTransitionAnimator

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext 
{
    return 0.25;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext 
{
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    if (self.presenting) {
        // custom presenting animation
    }
    else {
        // custom dismissing animation
    }
}

Solution 5

I struggled a bit with the Interface Builder of XCode 7 to set the Presentation Style as @VenuGopalTewari suggested. In this version, there seems to be no Over Current Context or Over Full Screen presentation mode for the segue. Thus, to make it work, I set the mode to Default:

enter image description here with enter image description here

Additionally I set the presentation mode of the modally presented view controller to Over Full Screen:

enter image description here

Share:
175,508

Related videos on Youtube

Michael
Author by

Michael

Updated on July 08, 2022

Comments

  • Michael
    Michael almost 2 years

    I'm trying to present a view controller modally, with a transparent background. My goal is to let both the presenting and presented view controllers's view to be displayed at the same time. The problem is, when the presenting animation finishes, the presenting view controller's view disappears.

    - (IBAction)pushModalViewControllerButtonPressed:(id)sender
    {
        ModalViewController *modalVC = [[ModalViewController alloc] init];
        [self presentViewController:modalVC animated:YES completion:nil];
    }
    

    I know I could just add the view as a subview, but I'd like to avoid this solution for some reason. How could I fix it?

    • Basil Bourque
      Basil Bourque over 10 years
      @TheKing Sounds like Michael, like me, wants the modal view to be translucent, to appear as a hovering gel layer over primary (presenting) view. Creates the sense of the user staying in the current context while making a quick setting, as opposed to going off to some other major functionality (in a separate view).
    • Hemang
      Hemang over 9 years
      This stackoverflow.com/q/27598846/1603234 make me smile, now your turn :)
    • Pankaj Wadhwa
      Pankaj Wadhwa about 9 years
      See my answer here stackoverflow.com/a/29794201/1606125 for iOS 8
    • Mojtaba Yeganeh
      Mojtaba Yeganeh over 8 years
    • Josef Rysanek
      Josef Rysanek over 7 years
      For iOS 10 is working UIModalPresentationOverFullScreen as inigo333 mentioned below.
    • Mitul Marsoniya
      Mitul Marsoniya about 7 years
      vc.modalPresentationStyle = UIModalPresentationOverFullScreen;
  • mxcl
    mxcl over 10 years
    Confirmed this works. NOTE that if your viewController is inside a navigationController then ensure its modalPresentationStyle is set also!
  • malex
    malex over 10 years
    I think that in the most common cases it is good idea to treat your navigation controller as presentingVC.
  • malex
    malex over 10 years
    Yes, using this modalPresentationStyle impossible to get presenting animation ((
  • João Nunes
    João Nunes over 10 years
    i have the down animation only
  • João Nunes
    João Nunes over 10 years
    Also the rotation is messed.
  • malex
    malex over 10 years
    Nevertheless it works :) It seems that Apple didn't care about such case.
  • malex
    malex over 10 years
    Are you sure you set YOUR_COLOR properly? For example, presentedVC.view.backgroundColor = [UIColor clearColor]; ?
  • tiguero
    tiguero over 10 years
    @alex yes it works sorry: my mistake was to set modalPresentationStyle to UIModalPresentationCurrentContext for the presentedVC instead of the prenstingVC.
  • Matt H
    Matt H almost 10 years
    Thanks - this is exactly what I needed - showing an initial "Help" screen on top of the main Home. Beautiful!
  • Thomas C. G. de Vilhena
    Thomas C. G. de Vilhena almost 10 years
    @mxcl And if your viewController's navigationController is itself inside a tabBarController then ensure its modalPresentationStyle is set also ;)
  • redent84
    redent84 almost 10 years
    It does work on iOS 7 and also on iPhone, the thing is that you have to specify the modalPresentationStyle = UIModalPresentationCurrentContext on the presenter view controller, and not in the presented one.
  • iGranDav
    iGranDav almost 10 years
    Yes it works but ONLY if you set this on the higher ViewController of your view hierarchy. (eg. a NavigationController or the instance of your slide menu view controller for example).
  • malex
    malex almost 10 years
    @user623396 write your iOS version. It perfectly works on iOS7 for example. Be sure you use "presentedVC" and "presentingVC" correctly.
  • Segev
    Segev almost 10 years
    I added a new answer with a quick animation solution.
  • user3099609
    user3099609 over 9 years
    It wasn't working for me because the presentingVC was in a navigation stack. Setting UIModalPresentationCurrentContext to the navigationViewController helped.
  • malex
    malex over 9 years
    @user3099609, I forgot to mention the fact that in many cases presentingVC is actually could be navigation controller or tabbar controller.
  • Mysteltainn
    Mysteltainn over 9 years
    @tiguero You have an "Embed Navigation Controller" right? You have to change the presentingVC to presentingVC.navigationViewController
  • u2Fan
    u2Fan over 9 years
    Note - It appears the target where you need to set modalPresentationStyle has changed. For example, in iOS 7, to get this to work, I needed to set the modalPresentationStyle of the View Controller(s) which was attempting to open the modal to UIModalPresentationCurrentContext. However, to get this to work in iOS8, I needed to set the modalPresentationStyle of the modal view which going to be displayed to UIModalPresentationOverCurrentContext.
  • Siriss
    Siriss over 9 years
    This is the only solution I could get to work. Very simple as well. Just add this to your presenting VC before the modal segue.
  • fullmoon
    fullmoon about 9 years
    I admire the 100% surers, it worked! The key is to apply it on the segue. Thank you a lot
  • Chanchal Raj
    Chanchal Raj about 9 years
    @ThomasC.G.deVilhena And how to set modelPresentationStyle of tabBarController? Because seems to be no such method.
  • malex
    malex about 9 years
    @ChanchalRaj , modelPresentationStyle is the property of UIViewController which is the superclass of UITabBarController.
  • Julian B.
    Julian B. about 9 years
    If using segues in your storyboards, you have to set the presentation style there. At least this is what worked for me.
  • Centurion
    Centurion about 9 years
    Today, I spend almost 3 hours browsing and searching for solution which works for both iOS7 and iOS8. Considering the fact this answer is 1.5 years old and I'm using ECSlidingViewController, this is the only solution which worked! Thanks @Mak.
  • RasTheDestroyer
    RasTheDestroyer about 9 years
    Perfect. Also, if you don't care about the animation, the 3 lines in the inner completion work perfectly Thanks!
  • Alex
    Alex almost 9 years
    Struggled long time to use the animation. your solution get me out of the problem. Thanks.
  • user3344977
    user3344977 over 8 years
    If you don't have your segue hooked up to a button and you're calling it programmatically then make sure to set an identifier and to call performSegueWithIdentifier instead of presentViewController
  • Sategroup
    Sategroup over 8 years
    Guys, I wrote the same code, and it doesn't work for me. I have trying for a week now, but no success. Can anyone please help? func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool { self.presentedViewController?.view.backgroundColor = UIColor.redColor() self.presentingViewController?.tabBarController?.modalPresen‌​tationStyle = UIModalPresentationStyle.CurrentContext return true; }
  • g212gs
    g212gs over 8 years
    I checked all the answer.. but for me your answer is perfect work.. "+1" for this. @Ted
  • alessioarsuffi
    alessioarsuffi over 8 years
    after 3 hours spent without any success found this, cheers, wish i could up vote more :D
  • LightMan
    LightMan about 8 years
    This worked for me, no code needed. I am using Xcode 7.2, swift and the target is iOS 8.0
  • endavid
    endavid about 8 years
    I tried all the other answers, but this is the only one that worked for me in iOS9.
  • Salman Khakwani
    Salman Khakwani about 8 years
    Thanks for Your Answer.
  • inigo333
    inigo333 about 8 years
    I added these three lines in the init method in the presented view controller, and works like a charm: self.providesPresentationContextTransitionStyle = YES; self.definesPresentationContext = YES; [self setModalPresentationStyle:UIModalPresentationOverCurrentCont‌​ext];
  • mojuba
    mojuba about 8 years
    Strangely, in my case it only worked after setting the modal style to UIModalPresentationCustom, and only if it's set right before presentViewController rather than in viewDidLoad.
  • devdc
    devdc almost 8 years
    On iOS 8+, I had to present a modal from a UINavigationController so presenting from a child did not provide me what I needed. Instead, sourceVC is self.navigationController. Also, only after setting the target presentation style as custom, I could see through it. [sourceVC setModalPresentationStyle:UIModalPresentationCurrentContext]‌​;, [targetVC setModalPresentationStyle:UIModalPresentationCustom]; Hopefully it will help someone.
  • Paul Linsay
    Paul Linsay almost 8 years
    Since iOS 8 all that's needed is UIModalPresentationOverFullScreen for the modalPresentationStyle of the ViewController being presented.
  • CopperCash
    CopperCash almost 8 years
    I thought I couldn't find a solution. Thanks a lot!
  • Augustine P A
    Augustine P A almost 8 years
    This worked for me too. +1 for the correct answer. Thanks :)
  • smileham
    smileham almost 8 years
    Note - Call presentedVC.modalPresentationStyle = UIModalPresentationOverCurrentContext in the presenting VC. Doesn't work in the presentedVC. Trust me, I tried.
  • SiavA
    SiavA over 7 years
    To make presented controller's view call layoutSubviews (on change orientations for ex.) use 'UIModalPresentationOverFullScreen' instead of 'UIModalPresentationOverCurrentContext'.
  • shinyuX
    shinyuX over 7 years
    Best answer here !
  • Josef Rysanek
    Josef Rysanek over 7 years
    Working on iOS 10.2.
  • GeneCode
    GeneCode over 7 years
    No code = Best answer. Bastian wins this game. Plz all +1 this answer.
  • William Hu
    William Hu about 6 years
    Xcoe 9.2/ iOS 11.2 swift .custom and .overFullScreen work.
  • William Hu
    William Hu about 6 years
    And seems if you set .overFullScreen the present view controller's viewWillAppear won't be called.
  • DawnSong
    DawnSong almost 6 years
    One more thing, presentedController.view.backgroundColor = #color# should be written in presentedController's viewDidLoad, or else presentedController's life is interrupted.
  • antonio081014
    antonio081014 over 5 years
    @devdc 's answer helped if your source VC is a UINavigationController or UITabBarController. Great tip.
  • Tomasz Nazarenko
    Tomasz Nazarenko over 5 years
    This was the hint that helped me among all the others. Thanks for your help.
  • bendytree
    bendytree almost 5 years
    After about 1000 attempts, I realized you need to set modalPresentationStyle before viewDidLoad. I did it in the constructor and it worked.
  • user578386
    user578386 almost 5 years
    This answer worked..spending more than a hour on this
  • Justin
    Justin over 3 years
    Coming to this thread in 2021 with Xcode 12.2 and iOS 14.2, this is the only solution that worked.
  • Pedro Trujillo
    Pedro Trujillo almost 3 years
    Thank you so much! This is the solution I was looking for.