11

I'm trying to do something that shouldn't be that complicated, but I can't figure it out. I have a UIViewController displaying a UITableView. I want to present a context menu when the user press on a row. I want this to be a semi-transparent view with labels and buttons. I could use an AlertView, but I want full control on the format of the labels and buttons and will like to use Interface Builder.

So I created my small view 250x290, set the alpha to .75 and create a view controller with the outlets to handle the different user events.

Now I want to present it. If I use presentModalViewController two (undesired) things happen 1) the view covers all of the screen (but the status bar). 2) It is semi-transparent, but what I see "behind" it its not the parent view but the applications root view.

Ive tried adding it as a subview, but nothing happens, so Im not doing something right:

RestaurantContextVC* modalViewController = [[[RestaurantContextVC alloc] initWithNibName:@"RestaurantContextView" bundle:nil] autorelease];
[self.view addSubview:modalViewController.view];

Is it possible to do what I want? Thanks in advance.

Gonso

Max B.
  • 881
  • 10
  • 21
gonso
  • 2,065
  • 5
  • 27
  • 35
  • Hi Gonso! I'm trying to do the same thing. In your final solution, did you end up having the popup modal view smaller? (Your post below suggests problems with background parent still interactive). Did you find a way to disable touch interaction with the parent screen while keeping the modal view smaller (besides partial transparency, the user can still see the parent info around the edges of the modal subview)? The round rect works for me, but I'm worried about user touching around the modal view and getting unexpected response. I want the only possible return to be buttons on the modal view. – Erika Electra Oct 03 '13 at 13:11

5 Answers5

11

I'm coding similar thing. My approach include.....

  1. Not using dismissModalViewControllerAnimated and presentModalViewController:animated.

  2. Design a customized full sized view in IB. In its viewDidLoad message body, set the background color to clearColor, so that space on the view not covered by controllers are transparent.

  3. I put a UIImageView under the controllers of the floating view. The UIImageView contains a photoshoped image, which has rounded corners and the background is set to transparent. This image view serves as the container.

  4. I uses CoreAnimation to present/dismiss the floating view in the modal view style: (the FloatingViewController.m)

    -  (void)viewDidLoad
    {
        [super viewDidLoad];
        [self.view setBackgroundColor:[UIColor clearColor]];
    
        [UIView beginAnimations:nil context:nil];
        [self.view setFrame:CGRectMake(0, 480, 320, 480)];
    
        [UIView setAnimationDuration:0.75f];
        [self.view setFrame:CGRectMake(0, 0, 320, 480)];
        [UIView commitAnimations];
    }
    
user1274820
  • 7,786
  • 3
  • 37
  • 74
wangii
  • 2,570
  • 1
  • 22
  • 29
3

wangii

Thats pretty much the solution I found. I load the view with loadNibNamed and then just add it on top with addSubView, like this:

//Show a view on top of current view with a wait indicator. This prevents all user interactions.
-(void) showWaitView{
    NSArray* nibViews =  [[NSBundle mainBundle] loadNibNamed:@"WaitView" owner:self options:nil];
#ifdef __IPHONE_2_1
    waitView = [ nibViews objectAtIndex: 0];
#else
    waitView = [ nibViews objectAtIndex: 1];
#endif          
    CGFloat x = self.view.center.x - (waitView.frame.size.width / 2);
    CGFloat y = self.view.center.y - (waitView.frame.size.height / 2);
    [waitView setFrame:CGRectMake(x,y,waitView.bounds.size.width,waitView.bounds.size.height)];
    [self.view addSubview:waitView];    
}

Could you elaborate on points 3 and 4?

What I did to give the view the round rect aspect is put it inside a round rect button.

This code will actually allow you to have a small floating view, but if the view is smaller that its parent, the user could interact with the visible part of the parent.

In the end I create my view with the same size, but kept the code just in case.

Gonso

gonso
  • 2,065
  • 5
  • 27
  • 35
  • Is waitView a UIView or a ViewController? I tried your code, and it told me that waitView doesn't have a frame. I have a nib prepared as well, but I can't turn a nib screen into a UIView, only a UIViewController! – Erika Electra Oct 20 '13 at 06:32
2

I would strongly consider using a navigation controller to slide in your subview instead of overlaying it. This is the expected model and any small benefit you may think you'll get by doing it your own way will be greatly offset by the principle of (least) surprise.

If you really really have to do it this way, I believe the trick is to add the first table view as a subview of a transparent "holding" view that the view controller maintains. Then add your new sub view as another subview of that.

philsquared
  • 22,403
  • 12
  • 69
  • 98
  • Can you add a small view over the parent view by using navigation controller? I guess to design a full view with controls on it as a small view and set the background as transparent? – David.Chu.ca Nov 08 '10 at 23:52
  • I have the same question: Is a small view overlay possible? I don't want to cover the whole screen with a slide-in either, although it's not the "sliding" that bothers me but the full coverage. I want to keep the parent partially visible because the user benefits from knowing other options besides the one that spawned the subview. I too want to set the background as transparent, but without enabling interaction with the back screen while the modal view is up. The modal view would have a cancel button, a detailed swipable UIImageView (toggle between images), and a confirm button. Thank you! – Erika Electra Oct 03 '13 at 13:13
1

What I did was create a UIViewController on top of my UINavigation controller in my app delegate and made it a property of a singleton object for convenience:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

//--- create root navigation controller
self.window.rootViewController = self.navigationController;

//--- create view controller for popups:
popupViewController = [[BaseViewController alloc] init];
popupViewController.view.backgroundColor = [UIColor clearColor];
popupViewController.view.hidden = true; //for rendering optimisation
[self.window addSubview:popupViewController.view];
[AppState sharedInstance].popupViewController = self.popupViewController;

//--- make all visible:
[self.window makeKeyAndVisible];

return YES;

}

At any point in my app, I can then call e.g.

MyViewController * myVC = [[UIViewController alloc] init];
//... set up viewcontroller and its view...
// add the view of the created view controller to the popup view:
[AppState sharedInstance].popupViewController.view.hidden = false;
[[AppState sharedInstance].popupViewController.view addSubview:myVC.view];

The BaseViewController used on the top just inherits from UIViewController and sets up a full-screen view:

//----- in BaseViewController implementation
- (void)loadView {
   //------- create root view:
   CGRect frame = [[AppState sharedInstance] getScreenFrame]; 
   rootView = [[VCView alloc] initWithFrame:frame];
   rootView.backgroundColor = [UIColor whiteColor];
   self.view = rootView;
}
Lenka Pitonakova
  • 979
  • 12
  • 14
1

Again, if you really want to do this, instead of adding a transparent "holding" view, since this pop-up is essentially modal, I would make it a subview directly of the window.

You might want to put in a transparent black shield behind it to prevent touches on the background and focus input on the popup.

But seriously, consider either popping a controller on the stack or using that alert view. Unless you've hired a $$ designer, it's probably not going to look appropriate on the iPhone.

Andrew Pouliot
  • 5,423
  • 1
  • 30
  • 34