How to change Modal background color to transparent in Objective-C How to change Modal background color to transparent in Objective-C objective-c objective-c

How to change Modal background color to transparent in Objective-C


Okay, so presentModalViewController doesn't offer this behavior... However it is still possible. I've created a category that works for me (and hopefully you). As an added bonus, it also prevents crashes related to dismissing and presenting modal views at the same time!

Header file:

////  UIViewController+overView.h//  Created by Kevin Lohman on 5/30/12.//#import <UIKit/UIKit.h>@interface UIViewController (OverView)- (void)presentOverViewController:(UIViewController *)modalViewController animated:(BOOL)animated;- (void)dismissOverViewControllerAnimated:(BOOL)animated;@end

Implementation File:

////  UIViewController+overView.m//  Created by Kevin Lohman on 5/30/12.//#import "UIViewController+overView.h"@implementation UIViewController (OverView)#define kUIViewControllerOverViewDismissNotification @"OverViewDismissNotification"const float kUIViewControllerOverViewAnimationDuration = 0.75;const NSInteger kUIViewControllerOverViewTag = 8008135; // Arbitrary number, so as not to conflict- (void)overViewDismissed{    [self autorelease];    [[NSNotificationCenter defaultCenter] removeObserver:self name:kUIViewControllerOverViewDismissNotification object:self.view];}- (void)presentOverViewController:(UIViewController *)modalViewController animated:(BOOL)animated{    UIView *toView = self.view;    CGRect finalRect = CGRectIntersection([[UIScreen mainScreen] applicationFrame], self.view.frame); // Make sure it doesn't go under menu bar    modalViewController.view.frame = finalRect;    modalViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;    modalViewController.view.tag = kUIViewControllerOverViewTag+modalViewController.modalTransitionStyle; // Hiding some info here :)    if(animated)    {        switch(modalViewController.modalTransitionStyle)        {            // Currently only cross dissolve and cover vertical supported... if you add support let me know.            case UIModalTransitionStyleCrossDissolve:            {                float beforeAlpha = modalViewController.view.alpha;                modalViewController.view.alpha = 0;                [toView addSubview:modalViewController.view];                [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{                    modalViewController.view.alpha = beforeAlpha;                }];                break;            }            case UIModalTransitionStyleCoverVertical:            default:            {                modalViewController.view.frame = CGRectMake(modalViewController.view.frame.origin.x, modalViewController.view.frame.size.height,                                                             modalViewController.view.frame.size.width, modalViewController.view.frame.size.height);                [toView addSubview:modalViewController.view];                [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{                    modalViewController.view.frame = finalRect;                }];                break;            }        }    }    else {        [toView addSubview:modalViewController.view];    }    [modalViewController retain]; // Keep it around until we dismiss it.    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(overViewDismissed) name:kUIViewControllerOverViewDismissNotification object:modalViewController.view]; // Release will happen when this notification is posted}NSInteger transitionStyleForTag(tag){    if (tag >= kUIViewControllerOverViewTag && tag <= kUIViewControllerOverViewTag+UIModalTransitionStylePartialCurl)    {        return tag-kUIViewControllerOverViewTag;    }    else {        return -1; // Not a Over View    }}- (void)dismissOverViewControllerAnimated:(BOOL)animated{    UIView *overView = transitionStyleForTag(self.view.tag) >= 0 ? self.view : nil; // Can dismiss ourselves    for(UIView *subview in self.view.subviews)    {        if(transitionStyleForTag(subview.tag) >= 0)            overView = subview; // Keep going, lets dismiss last presented first    }    if(!overView) return; // None to dismiss    if(animated)    {        switch(transitionStyleForTag(overView.tag))        {            // Currently only cross dissolve and cover vertical supported... if you add support let me know.            case UIModalTransitionStyleCrossDissolve:            {                float beforeAlpha = overView.alpha;                [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{                    overView.alpha = 0;                } completion:^(BOOL finished) {                    [overView removeFromSuperview];                    overView.alpha = beforeAlpha;                    [[NSNotificationCenter defaultCenter] postNotificationName:kUIViewControllerOverViewDismissNotification object:overView];                }];                break;            }            case UIModalTransitionStyleCoverVertical:            default:            {                [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{                    overView.frame = CGRectMake(0, overView.frame.size.height, overView.frame.size.width, overView.frame.size.height);                } completion:^(BOOL finished) {                    [overView removeFromSuperview];                    [[NSNotificationCenter defaultCenter] postNotificationName:kUIViewControllerOverViewDismissNotification object:overView];                }];                break;            }        }    }    else {        [overView removeFromSuperview];        [[NSNotificationCenter defaultCenter] postNotificationName:kUIViewControllerOverViewDismissNotification object:overView];    }}@end

And then to use it, simply use presentOverViewController instead of presentModalViewController and dismissOverViewController instead of dissmissModalViewController.

There are a couple of limitations:

  1. You have to present to the root-most view controller, so if you wantto cover the whole screen and you've got a VC inside of aUINavigationController, present it to the navigation controller.
  2. May be some issues with rotation (I didn't see any) on older iOSbuilds (4.0 or so)
  3. Currently only handles Cross Dissolve and Cover Vertical animations.


The answer for me was one line of code, added to the parent view controller before presenting the modal view controller:

self.modalPresentationStyle = UIModalPresentationCurrentContext;

This will stop the parent view from being removed once the modal view has been added.


iOS doesn't support transparency when presenting a view modally.