my app doesn't support rotation. But I want to present a QLPreviewController that supports rotation.
I present the QLPreviewController like this:
[self presentModalViewController:thePrevController animated:NO];
How can I do this?
Enable all rotations in your application plist file. This will make all views rotate irrespective of the settings in the view controller.
Then subclass your root UINavigationController as below, adding the rotation control code for iOS5 and 6 depending on your requirements:
I was updating an old app with MainWindow.xib, so I changed the class of the navigation controller in the xib file to CustomNavigationController. But in a more modern app with say a main menu, you'd instantiate the nav controller like this:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
MainMenuVC *masterViewController = [[MainMenuVC alloc] initWithNibName:#"MainMenuVC" bundle:nil];
self.navigationController = [[CustomNavigationController alloc] initWithRootViewController:masterViewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
Subclass UINavigationController
#import <UIKit/UIKit.h>
#interface CustomNavigationController : UINavigationController
#end
#import "CustomNavigationController.h"
#interface CustomNavigationController ()
#end
#implementation CustomNavigationController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL)shouldAutorotate
{
return NO;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
#end
Then subclass the QLPreview controller so you can override the rotation code which will enable rotation for the QLPreviewController only. The rest of the app with views pushed from your CustomNavContoller will not rotate as the CustomNavigationController is locked.
I added this interface and implementation at the top of the view controller where I wanted to present the QLPreviewController.
#interface RotatingQLPreviewController : QLPreviewController
#end
#implementation RotatingQLPreviewController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
-(BOOL)shouldAutorotate
{
return YES;
}
#end
Then present your QLPreviewController using your subclass.
RotatingQLPreviewController *preview = [[RotatingQLPreviewController alloc] init];
preview.dataSource = self;
[self presentViewController:preview
animated:YES
completion:^(){
// do more stuff here
}];
This method should work for other modal views that you want to rotate, but I haven't tried it.
I implemented this method in the latest app I'm working on and works in both iOS5 and 6.
Hope it helps.
The Twitter app is a tab bar app on the iPhone. Nothing in any of the tabs will rotate, yet, when you click on a link from a tweet, the view controller that is pushed on top of it IS allowed to rotate. The only rotations I have ever doe is from tilting the device, landscape or portrait, but I don't understand how to use 2d transformations and animations to rotate views.
How do you rotate any view with that's a subclass of UIView?
You can use UIView animations and Transform methods.
For rotating 90 degrees:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
imageView.transform = CGAffineTransformMakeRotation(M_PI_2);
[UIView commitAnimations];
Hey I had a similar problem with rotation. I had a tabbar app that I wanted to remain portrait but have a video player that allowed all rotations.
I managed to do this fairly easily by sub-classing the tabbar and only allowing portrait rotation while attaching the video player to the Root View Controller that allowed all rotations. Check out my original post here. Hope its of some help!
Check this tutorial, i think this is what you wanted to do
http://www.raywenderlich.com/9864/how-to-create-a-rotating-wheel-control-with-uikit
http://www.raywenderlich.com/5478/uiview-animation-tutorial-practical-recipes
This is the best and perfect work for me and i think this the right answer.
Just Give Number How many Times You Want To Rotate In Place Of 50 In toValue
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
NSNumber *currentAngle = [CircleView.layer.presentationLayer valueForKeyPath:#"transform.rotation"];
rotationAnimation.fromValue = currentAngle;
rotationAnimation.toValue = #(50*M_PI);
rotationAnimation.duration = 50.0f; // this might be too fast
rotationAnimation.repeatCount = HUGE_VALF; // HUGE_VALF is defined in math.h so import it
[CircleView.layer addAnimation:rotationAnimation forKey:#"rotationAnimationleft"];
Ref From How to implement UIViewController rotation in response to orientation changes?
I do this by having a root view controller (this could be a UITabBarController) and in it's viewDidLoad method i subscribe to rotation events:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(didRotate:)
name:#"UIDeviceOrientationDidChangeNotification"
object:nil];
Then in the didRotate: method i look at which view controller is visible when the rotation happened, and what orientation the phone is in:
- (void) didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
/*
DEVICE JUST ROTATED TO PORTRAIT MODE
orientation == UIDeviceOrientationFaceUp ||
orientation == UIDeviceOrientationFaceDown
*/
if(orientation == UIDeviceOrientationPortrait) {
/*
DEVICE JUST ROTATED TO LANDSCAPE MODE
*/
}else if(orientation == UIInterfaceOrientationLandscapeLeft ||
orientation == UIInterfaceOrientationLandscapeRight) {
}
}
Within that didRotate: you can look at which is the visible viewController and do what you want from there.
I present a modal view controller in landscape mode when a particular view controller is visible and the phone is rotated into landscape. If any other view controller is visible, i ignore the event.
I force my modal view controller to display in landscape mode in its viewWillAppear method - i can give anyone this code if they want it.
Hope this helps.
You are able to implement the shouldAutorotateToInterfaceOrientation method. In the Twitter app i am guessing they allow only portrait orientation for the tabBarController, but allow landscape in the modalViewController using this method. look it up in the documentation, it's pretty simple I think. I hope this answers your question!
#Mangesh-Vyas has some good information but doesn't quite answer the question (as I read it). The reason that the views that Twitter (among other apps) presents can rotate, when the tabbar or navbar cannot, is because they are presented modally. Views which are presented modally aren't constrained to the allowable orientations of the controller which presented them.
Edit:
Perhaps you are expecting a stock UIViewController to rotate. If so then you will be disappointed, as only (to the best of my knowledge) custom subclasses can be made to rotate to arbitrary interfaceOrientations. The following code will do the trick:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
Edit 2:
Here's the code that makes the whole thing go:
AppDelegate.m
#import "RotateViewController.h"
#interface AppDelegate () {
UINavigationController* nc;
}
- (void)pushVC;
- (void)openVC;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIViewController* vc = [[UIViewController alloc] init];
vc.view.backgroundColor = [UIColor blueColor];
vc.title = #"Root";
UIButton* b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
b.frame = CGRectMake(50, 150, 220, 40);
[b.titleLabel setText:#"Push VC"];
[b addTarget:self action:#selector(pushVC) forControlEvents:UIControlEventTouchUpInside];
[vc.view addSubview:b];
b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
b.frame = CGRectMake(50, 200, 220, 40);
[b.titleLabel setText:#"Modal VC"];
[b addTarget:self action:#selector(openVC) forControlEvents:UIControlEventTouchUpInside];
[vc.view addSubview:b];
nc = [[UINavigationController alloc] initWithRootViewController:vc];
UITabBarController* tc = [[UITabBarController alloc] init];
[tc addChildViewController:nc];
// uncomment this line to see this work in a nav controller
// [self.window setRootViewController:nc];
[self.window setRootViewController:tc];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)openVC {
RotateViewController* rc = [[RotateViewController alloc] init];
[nc presentModalViewController:rc animated:YES];
}
- (void)pushVC {
RotateViewController* rc = [[RotateViewController alloc] init];
[nc pushViewController:rc animated:YES];
}
RotateViewController is a stock subclass of UIViewController with the shouldAutorotate function from above.
Nota bene UITabBarControllers can rotate to a given interface orientation if, and only if, every one of their child view controllers returns YES for that orientation. UINavigationViewControllers can rotate to a given interface orientation if their top view controller returns YES for that interface orientation.
am creating a application which is support all type of orientation, i added one UIView on the UIWindow.but on rotating the device the view which is added on the Window is not rotating. the view always showing default (Portrait). please help me to fix this problem ...
Thanks in advance
You need to add a UIViewController on your UIWindow.
UIView doesn't handle rotations, UIViewController does.
So, all you need is to create a UIViewController, which implements shouldAutorotateToInterfaceOrientation and sets this controller as a rootViewController to your UIWindow
Something like that:
- (void) makeWindow
{
UIViewController * vc = [[[MyViewController alloc] init] autorelease];
UIWindow * window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[window setRootViewController:vc];
[window makeKeyAndVisible];
}
#interface MyViewController : UIViewController
#end
#implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
//your view initialization here
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
#end
I have a TabbarController with different ViewControllers.
Some of these ViewControllers should autorotate and one ViewController should be presented only in PORTRAIT.
I fill the Tabbar with the following procedure:
ChartThemeViewController *chartViewController = [[ChartThemeViewController alloc]
initWithTheme:chartThemeDict];
UINavigationController *theNavigationController = [[UINavigationController alloc]
initWithRootViewController:chartViewController];
[chartViewController release];
[localViewControllersArray addObject:theNavigationController];
[theNavigationController release];
tabBarController.viewControllers = localViewControllersArray;
The ChartThemeViewController is a subclass of ThemeViewController.
ThemeViewController is a subclass of UIViewController.
If I override 'shouldAutorotateToInterfaceOrientation' in the subclasses of ThemeViewController, and return YES in all subclasses and return NO in ChartThemeViewController... it happens that all the ViewControllers don't autorotate.
mmmmhhh... hope you can understand this...
How can I solve this problem?
many thanks
jens
I believe the trick to selective autorotation within an instance of UITabBarController is as follows: Subclass UITabBarController and override the method -(BOOL)shouldAutorotateToInterfaceOrientation: with the following:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return [[self selectedViewController] shouldAutorotateToInterfaceOrientation:interfaceOrientation];
};
Now, if you select your portrait-only tab and rotate to landscape, the application will stay in portrait.
A new problem here, though, is as follows: select a tab that does support landscape; rotate to landscape; select a tab that only supports portrait. Uh oh. The portrait-only view controller is being displayed in landscape. Unfortunately, there is no way to force a view controller to a specific orientation.
You can look here for a description of the problem: How to force a screen orientation in specific view controllers?
As you can see, there is no real solution.
I would recommend disabling all tabs that do not support the current orientation. You can override -(void)didAutorotateToInterfaceOrientation: in your UITabBarController subclass with the following to achieve this:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
UIInterfaceOrientation toInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
NSArray *items = [[self tabBar] items];
for (NSUInteger i = 0; i < [items count]; i ++)
{
UITabBarItem *item = [items objectAtIndex:i];
if (![[[self viewControllers] objectAtIndex:i] shouldAutorotateToInterfaceOrientation:toInterfaceOrientation])
{
[item setEnabled:NO];
}
else
{
[item setEnabled:YES];
};
};
};
If you do not wish to do this, then consider altering your interface to be able to support the same orientations in all of your view controllers.
Hope this helps,
Ryan
I'm trying to create a transparent modal View on top of my navigation controller. Does anyone know if this is possible?
A modal view will cover the view it is pushed on top of as well as the navigation bar for your navigation controller. However, if you use the -presentModalViewController:animated: approach, then once the animation finishes the view just covered will actually disappear, which makes any transparency of your modal view pointless. (You can verify this by implementing the -viewWillDisappear: and -viewDidDisappear: methods in your root view controller).
You can add the modal view directly to the view hierarchy like so:
UIView *modalView =
[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
modalView.opaque = NO;
modalView.backgroundColor =
[[UIColor blackColor] colorWithAlphaComponent:0.5f];
UILabel *label = [[[UILabel alloc] init] autorelease];
label.text = #"Modal View";
label.textColor = [UIColor whiteColor];
label.backgroundColor = [UIColor clearColor];
label.opaque = NO;
[label sizeToFit];
[label setCenter:CGPointMake(modalView.frame.size.width / 2,
modalView.frame.size.height / 2)];
[modalView addSubview:label];
[self.view addSubview:modalView];
Adding the modalView as a subview to the root view like this will not actually cover the navigation bar, but it will cover the entire view below it. I tried playing around with the origin of the frame used to init the modalView, but negative values cause it to not display. The best method that I found to cover the entire screen besides the status bar is to add the modalView as a subview of the window itself:
TransparentModalViewAppDelegate *delegate = (TransparentModalViewAppDelegate *)[UIApplication sharedApplication].delegate;
[delegate.window addSubview:modalView];
The easiest way is to use modalPresentationStyle property of navigationController (but you'll have to make animation by yourself):
self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:modalViewController animated:NO];
modalViewController.view.alpha = 0;
[UIView animateWithDuration:0.5 animations:^{
modalViewController.view.alpha = 1;
}];
I accomplish this most easily by setting up an "OverlayViewController" that sits above all other subviews of my window or root view. Set this up in your app delegate or root view controller, and make OverlayViewController a singleton so that it can be accessed from anywhere in your code or view controller hierarchy. You can then call methods to show modal views, show activity indicators, etc, whenever you need to, and they can potentially cover any tab bars or navigation controllers.
Sample code for root view controller:
- (void)viewDidLoad {
OverlayViewController *o = [OverlayViewController sharedOverlayViewController];
[self.view addSubview:o.view];
}
Sample code you might use to display your modal view:
[[OverlayViewController sharedOverlayViewController] presentModalViewController:myModalViewController animated:YES];
I haven't actually used -presentModalViewController:animated: with my OverlayViewController but I expect this would work just fine.
See also: What does your Objective-C singleton look like?
I had this same problem and in order to The solution is to add the modal view with addSubview: and animate the change in the view hierarchy with UIView’s animateWithDuration:delay:options:animations:completion:
I added a property and 2 methods to a subclass of UIViewController (FRRViewController) that includes other functionalities. I will be publishing the whole stuff on gitHub soon, but until then you can see the relevant code below. For more info, you can check my blog: How to display a transparent modal view controller.
#pragma mark - Transparent Modal View
-(void) presentTransparentModalViewController: (UIViewController *) aViewController
animated: (BOOL) isAnimated
withAlpha: (CGFloat) anAlpha{
self.transparentModalViewController = aViewController;
UIView *view = aViewController.view;
view.opaque = NO;
view.alpha = anAlpha;
[view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UIView *each = obj;
each.opaque = NO;
each.alpha = anAlpha;
}];
if (isAnimated) {
//Animated
CGRect mainrect = [[UIScreen mainScreen] bounds];
CGRect newRect = CGRectMake(0, mainrect.size.height, mainrect.size.width, mainrect.size.height);
[self.view addSubview:view];
view.frame = newRect;
[UIView animateWithDuration:0.8
animations:^{
view.frame = mainrect;
} completion:^(BOOL finished) {
//nop
}];
}else{
view.frame = [[UIScreen mainScreen] bounds];
[self.view addSubview:view];
}
}
-(void) dismissTransparentModalViewControllerAnimated:(BOOL) animated{
if (animated) {
CGRect mainrect = [[UIScreen mainScreen] bounds];
CGRect newRect = CGRectMake(0, mainrect.size.height, mainrect.size.width, mainrect.size.height);
[UIView animateWithDuration:0.8
animations:^{
self.transparentModalViewController.view.frame = newRect;
} completion:^(BOOL finished) {
[self.transparentModalViewController.view removeFromSuperview];
self.transparentModalViewController = nil;
}];
}
}
Here's what I did to solve the problem - Google the details but this approach worked very well for me:
Take a screenshot of the underlying view. https://devforums.apple.com/message/266836 - this leads to a ready-made method that returns a UIView for the current screen.
Hand the screenshot to the modal view (I used a property)
Present the modal view
In the modal view controller's viewDidAppear, set the image as UIImageView at index 0. Adjust the vertical position of the image by the height of the status bar.
In the modal view controller's viewWillDisappear, remove the image again
The effect is:
The view animates in as any modal view does - the semi transparent parts of the modal view glide over the existing view
As soon as the animation stops, the background is set to the screenshot - this makes it appear as if the old view is still underneath even though it isn't.
As soon as the modal view's disappear animation starts, the image is removed. The OS meanwhile shows the old navigation view so the modal view transparently glides away and out of sight as you'd expect.
I tried animating in my own overlay view but it didn't work very well. I got a crash with no indication as to what has crashed. Rather than chase this down I did the bg view & Works really well.
Code in the modal view - I think you can figure out the rest, namely setting the property modalView.bgImage...
- (void)viewDidAppear:(BOOL)animated {
// background
// Get status bar frame dimensions
CGRect statusBarRect = [[UIApplication sharedApplication] statusBarFrame];
UIImageView *imageView = [[UIImageView alloc] initWithImage:self.bgImage];
imageView.tag = 5;
imageView.center = CGPointMake(imageView.center.x, imageView.center.y - statusBarRect.size.height);
[self.view insertSubview:imageView atIndex:0];
}
- (void)viewWillDisappear:(BOOL)animated {
[[self.view viewWithTag:5] removeFromSuperview];
}
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:newview animated:YES];
and make sure you setup the modal view background to be transparent,
self.view.background = .... alpha:0.x;
if you set modalPresentationStyle for the modal view controller to:
viewController.modalPresentationStyle = 17;
The view in the background is not removed. (TWTweetComposeViewController use it).
I did not try to pass App Store review with this code though
This post about displaying a semi-transparent "Loading..." view might give a few pointers on how to proceed.
Yeah, you have to add the view manually, and if you want to slide in from the bottom or whatever you have to do the animation yourself too.
I wrote a class to do this, and a semi-modal datepicker using that class as an example.
You can find documentation in this blog post, the code is on github
I've been researching this same issue for the past week. I tried all the various answers and examples found in Google and here on StackOverflow. None of them worked that well.
Being new to iOS programming, I wasn't aware of something called UIActionSheet. So if you're trying to accomplish this in order to show a modal overlay of buttons (such as a modal asking someone how they want to share something), just use UIActionSheet.
Here is a webpage that shows an example of how to do this.
I got this idea from https://gist.github.com/1279713
Prepare:
In the modal view xib (or scene using storyboard), I setup the full-screen background UIImageView (hook it with the .h file and give it a property "backgroundImageView") with 0.3 alpha. And I set the view (UIView) background color as plain black.
Idea:
Then in "viewDidLoad" of the modal view controller I capture the screenshot from the original status and set that image to the background UIImageView. Set the initial Y point to -480 and let it slide to Y point 0 using 0.4-second duration with EaseInOut animation option. When we dismiss the view controller, just do the reverse thing.
Code for the Modal View Controller Class
.h file:
#property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView;
- (void) backgroundInitialize;
- (void) backgroundAnimateIn;
- (void) backgroundAnimateOut;
.m file:
- (void) backgroundInitialize{
UIGraphicsBeginImageContextWithOptions(((UIViewController *)delegate).view.window.frame.size, YES, 0.0);
[((UIViewController *)delegate).view.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
backgroundImageView.image=screenshot;
}
- (void) backgroundAnimateIn{
CGRect backgroundImageViewRect = backgroundImageView.frame;
CGRect backgroundImageViewRectTemp = backgroundImageViewRect;
backgroundImageViewRectTemp.origin.y=-480;
backgroundImageView.frame=backgroundImageViewRectTemp;
[UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationCurveEaseInOut animations:^{
backgroundImageView.frame=backgroundImageViewRect;
} completion:^(BOOL finished) {
}];
}
- (void) backgroundAnimateOut{
CGRect backgroundImageViewRect = backgroundImageView.frame;
backgroundImageViewRect.origin.y-=480;
[UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationCurveEaseInOut animations:^{
backgroundImageView.frame=backgroundImageViewRect;
} completion:^(BOOL finished) {
}];
}
In viewDidLoad, simply call:
[self backgroundInitialize];
[self backgroundAnimateIn];
In anywhere we dismiss the modal view controller, we call:
[self backgroundAnimateOut];
Please note that this will ALWAYS animate the background image. So if this modal view controller transition style (or the segue transition style) is not set to "Cover Vertical", you may not need to call the animation methods.
I finally accomplished this, for a navigation or tab bar interface, by combining an overlay view controller (see: pix0r's answer) that's hidden / un-hidden before hiding or showing a view controller based on this very good blog post.
Concerning the view controller, the tip is to make its background view the clearColor, then the semi-transparent overlay view is visible and whatever views are added as subviews in the view controller are in front and most importantly opaque.
I've created open soruce library MZFormSheetController to present modal form sheet on additional UIWindow. You can use it to present transparency modal view controller, even adjust the size of the presented view controller.
For iOS 8+ you can use UIModalPresentationOverCurrentContext presentation style for presented view controller to easy achieve desired behavior.
UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.9f];
viewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:viewController animated:YES completion:nil];
If you also need to support iOS 7 - check this thread.
You can achieve transparent/semi-transparent modal view effect by overlaying a transparent/semi-transparent button on both the view and the navigation bar.
You can access the navigation bar through the navigationBar property of the UINavigationController.
I found that UIButton unlike UILabel will trap mouse events - hence giving the correct modal behavior.
I just found a workaround for that. Just create a 1X1 of UIViewController and add it to your parent view controller. And show the transparent modal view controller in that UIViewController.
on viewDidLoad;
self.dummyViewController = [[UIViewController alloc] init];
[self.dummyViewController.view setFrame:CGRectMake(0, 0, 1, 1)];
[self.view addSubView:self.dummyViewController.view];
when you need to open a transparentViewController;
[self.dummyViewController presentModalViewController:yourTransparentModalViewController animated:true];
If you need a screen like the attached one, the below code may help you.
The code:
MyViewController * myViewController = [[MyViewController alloc] initWithNibName:nibName bundle:nil];
UINavigationController * myNavigationController = [[UINavigationController alloc] initWithRootViewController: myViewController];
myNavigationController.modalPresentationStyle = UIModalPresentationPageSheet;
[self presentModalViewController: myNavigationController animated:YES];
If say you want a screen overlay, use the parentViewController.view, it will place above navigation bar ++
MyCustomViewController* myOverlayView = [[MyCustomViewController alloc] init];
[self.parentViewController.view addSubview:myOverlayView];
This worked for me:
UIViewController *modalViewController = [[UIViewController alloc] init];
modalViewController.view.backgroundColor = [UIColor whiteColor] colorWithAlpha:0.5];
[self showDetailViewController:modalViewController sender:nil];