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:
- 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.
- May be some issues with rotation (I didn't see any) on older iOSbuilds (4.0 or so)
- 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.