tags:

views:

6336

answers:

8

I'm trying to create a transparent modal View on top of my navigation controller. Does anyone know if this is possible?

+3  A: 

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?

pix0r
This approach works very well - one odd thing, I make my overlay view in IB and set it's view property to hidden, but when the view is loaded (and added to the sub-view) it's always hidden == NO - I have to explicitly set it to YES initially, in say -viewDidLoad:
petert
Okay, now I understand how NIB's are loaded and initialised. Since the overlay view is simple to set up, now I'm implementing -loadVIew in my class.
petert
+19  A: 

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];
[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];
phatblat
Thanks a lot, I'll give it a try.
leafeater
I found this discussion quite useful for this problem.http://www.iphonedevsdk.com/forum/iphone-sdk-development/14315-modal-view-semi-transparent-background.htmlThe approach that worked for me was to manually animate the appearance of a subview, instead of using apple modal views
CVertex
+1  A: 

This post about displaying a semi-transparent "Loading..." view might give a few pointers on how to proceed.

Stephen Darlington
A: 

Have you considered using UIAlertView? It is fairly flexibile...

nicktmro
A: 

Well, looks that using this approach we just need to add some animation... I don't really know why apple decided to make modal views totally opaque...

if yo add a "transparent modal view" you can see the wanted transparency effect in the animation... but after it finishes... bang it becomes opaque.

Well, anyway I like the subview + animation approach!!

A: 

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.

Shivaraj Tenginakai
A: 

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 handy blog post: link text

Concerning the view controller, the tip is to make it's background view the 'clear color', then the semi-transparent overlay view is visible and whatever views are added as subviews in the view controller are in front and mostly importantly opaque.

petert
A: 

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

Nathan Reed