4

I'm building an iOS 6 iPhone app in Xcode 4.6 and am wondering about the best way to achieve the following type of popup window:

PopoverScreenshot

Specifically, the iPhone screenshot on the right, where, if a user taps on a face or UIView in the main window, a partially transparent popover appears with more detailed information -- such as a portrait photo and textual data -- but the original view (a photo collection here) remains visible, and the timers/counters continue ticking down in that view.

I thought this would be a possible solution iPhone Modal View Smaller that the screen but it doesn't work for me. Not shown above is a cancel button that I am also planning to put in the popover, so that the user can return to the view underneath. When the timer expires, the detailed view also disappears.

Should I use presentModalViewController and the presenter/presented scheme, or use a parent-child-view relationship with a storyboard segue, or should I use loadNibNamed, or some kind of hack to overcome the iPhone's limitation of displaying a non-full-screen modal view? It'll cover most of the screen but I want to make sure the view underneath is visible and still active, since it provides information to the user that isn't in the popover (timer, etc.). The user won't need to interact with the screen below, but I'd like it to be partially visible.

I designed the popup view as a separate viewcontroller in my main storyboard, not as a xib file. The connections and outlets are formed from interface builder to my code, called ProfileViewController.

WARNING: My terminology may be incorrect and inaccurate. The popup or popover can be a UIView, UIViewController, UIWindow, or whatever works best programatically to solve the problem. I'm not tied to it being a certain widget type, as long as the functionality mirrors what I'm seeking.

Thanks in advance for your suggestions!

Community
  • 1
  • 1
Erika Electra
  • 1,854
  • 3
  • 20
  • 31
  • 3
    my suggestion is Use UIView and set its alpha property and background color is black i.e. view.alpha=0.8f – Kalpesh Oct 22 '13 at 05:12
  • can make clearcolor of viewcontroller and Design new uiview on it as u wish.. then [self.view addsubview:your_viewcontroller.view]; – Agent Chocks. Oct 22 '13 at 05:15
  • RE: Kalpesh. Thanks. Should I subclass UIView for the popup, or create an accompanying ViewController for it? Not quite sure where to put the handles (outlet connections) for items that appear in a UIView -- the underlying ViewController? I've subclassed UIView before to create widgets I can place in IB, but never designed a custom one in Interface Builder. – Erika Electra Oct 22 '13 at 05:19
  • 1
    @Cindeselia you can create popview programatically at run time. add it into window . Check my answer. – Kalpesh Oct 22 '13 at 05:28

4 Answers4

16

do you want to achieve this?

enter image description here

Here are two different viewControllers one above other one. vc2 is a childViewController of vc1 with a transparent background. In your case you can put a UILabel top of the stack with backgroundColor black and alpha = 0.5.

All events of vc2 will fire on vc2.m. Use this code on image click:

- (IBAction)imageClick 
{
    vc2 *viewController = [[vc2 alloc]init];
    [self addChildViewController:viewController];
    viewController.view.frame = self.view.frame;
    [self.view addSubview:viewController.view];
    viewController.view.alpha = 0;
    [viewController didMoveToParentViewController:self];

    [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^
     {
         viewController.view.alpha = 1;
     }
                     completion:nil];
}

And in vc2.m put this on viewDidLoad to make this viewControllertransparent.

self.view.backgroundColor = [UIColor clearColor];
self.view.opaque = YES;

Making transparent view a viewController will make your code clean as all code of vc2 will be in a separate class.

EDIT

So do one thing, First add a UIView to your xib which will be a rounded border and frame will be that you want as per your screenshot.

For rounded border, you can use this category. backgroundColor of this UIView will be clearColor:

- (void)setRoundedBorder:(float) radius borderWidth:(float)borderWidth color:(UIColor*)color
{
    CALayer * l = [self layer];
    [l setMasksToBounds:YES];
    [l setCornerRadius:radius];
    // You can even add a border
    [l setBorderWidth:borderWidth];
    [l setBorderColor:[color CGColor]];
}

Now put a UILabel/UIView/UIImage whose frame is equal to UIView above and alpha is 0.5 with black background color. You can do this directly from xib. No need to set frame through code.

Then start putting your other controls inside UIView

Vaibhav Saran
  • 12,848
  • 3
  • 65
  • 75
  • Yeah, your screenshot is basically what I want, except with mine being transparent and also giving the user an option to click buttons on it to return info back to the calling ViewController. Let me give this a try, I'll get back. – Erika Electra Oct 22 '13 at 05:40
  • This appeared on the line viewController.view.frame = self.view.frame;.........Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSPlaceholderMutableString initWithString:]: nil argument' *** First throw call stack: (0x160b012 0x1318e7e 0x160adeb 0xd49e68 0x1d569 0x1d06c 0x33e1c7 0x33e232 0x5724 0x61db 0x52785a 0x52699b 0x5280df 0x52ad2d 0x52acac 0x522a28 0x28f972 0x28fe53 0x26dd4a 0x25f698 0x266ddf9 0x266dad0 0x1580bf5 0x1580962 0x15b1bb6 0x15b0f44 0x15b0e1b 0x266c7e3 0x266c668 0x25cffc 0x221d 0x2145) libc++abi.dylib: terminate called throwing an exception – Erika Electra Oct 22 '13 at 05:54
  • As I said, put a semi transparent `UILabel` with `label.frame = self.view.frame`. And for cross button click use this code: `[UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^ { self.view.alpha = 0; } completion:^(BOOL finished) { if(finished) { [self.view removeFromSuperview]; } }];` – Vaibhav Saran Oct 22 '13 at 06:48
  • Sorry for asking another question, but why do we need the UILabel? Shouldn't we make the top View in the stack something like a UIView with a transparent background, or a UIImage with a transparent image loaded? (Just wondering, as it seems counterintuitive) – Erika Electra Oct 22 '13 at 07:13
  • I just tried putting a UILabel or a UIImageView at the top of the stack, and it deleted everything I already had in my stack! Copy/paste didn't work either, it just took one of my copied elements and replaced the top of the stack; everything else disappeared. How do I keep the stuff in the top View that I already have drawn and laid out (and attached)? – Erika Electra Oct 22 '13 at 07:18
  • yes you can use anything `UIImage`, `UILabel`, or `UIView`. Both 2 are more memory efficient than `UIImage`, thats it. Top of stack means `UILabel/UIImage` will look at top of that `viewController's` other `views` in `xib` or `storyboard` so that will go underneath all the `views` – Vaibhav Saran Oct 22 '13 at 07:26
  • Where I set label.frame = self.view.frame? It seems like I can load the xib from Storyboard using instantiateViewControllerUsingIdentifier but as soon as I refer to anything to do with its frame, the app crashes! Here is the new error message – Erika Electra Oct 22 '13 at 07:31
  • reason: '*** -[NSPlaceholderMutableString initWithString:]: nil argument' *** First throw call stack: – Erika Electra Oct 22 '13 at 07:33
  • Thank you for your patience! Okay, for the most part, this worked. The only thing I still need to debug is the view not covering the places I think it would. In storyboard editor, it of course covers the entire screen, and I took out the battery bar, even. But when I load it, despite setting the frame to self.frame, the individual elements in the popup are shifted down so they are cut off at the bottom of the screen. The individual items are okay, it just doesn't start at the top like it should. Any way to align everything properly so they start at the top? – Erika Electra Oct 22 '13 at 09:20
  • could you send me a screenshot. – Vaibhav Saran Oct 23 '13 at 05:18
  • I fixed the frame bounds, but I do have one question. If I am waiting for some kind of return value from the popup (like making a choice or entering a value) so the lower view can return, how can I do that? Right now, I am calling the view to come up and returning a value, but the value gets returned before the view is displayed, so it's a junk value. [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^ { profViewController.view.alpha = 1; } completion:nil]; return profViewController.neededIndex; } – Erika Electra Oct 23 '13 at 08:25
  • This solution will not show on top of the tab bar, as the initial mockup indicates. Also it will not work properly if you have a navigation bar (will not cover it). Same goes for modal views. Same goes for cases when there are multiple child VCs on the same screen. – user3099609 Oct 15 '14 at 08:43
7

Try this

// create a new view
  UIView *viewPopup=[[UIView alloc]init];
  [viewPopup setBackgroundColor:[UIColor blackColor]];
  viewPopup.alpha=0.6f;

 // add into window
 AppDelegate *appdelgateobj=(AppDelegate *)[[UIApplication sharedApplication]delegate];
 [appdelgateobj.window addSubview:viewPopup];
 [appdelgateobj.window bringSubviewToFront:viewPopup];
Kalpesh
  • 5,336
  • 26
  • 41
  • Kalpesh: Thanks, I like the simplicity of the solution. My concern is how can I place custom elements into the popup? (Well, I know how to add properties and member vars, but I meant like knowing where elements that I want to appear on the screen need to go to look right, etc. Any way to design the new view in Interface Builder? Like instead of text numbers, I have an animated barGraph. I know how to instantiate those in code, but not to place them in exactly the right location. Is this just trial and error?) – Erika Electra Oct 22 '13 at 05:33
  • @Korben use this [viewPopup removeFromSuperview]; viewPopup=nil; – Kalpesh Apr 23 '15 at 05:15
5

Follow below step for transparent view :

step 1: enter image description here

step 2:

enter image description here

  • Whenever you want it Transpertview.hidden=NO:
  • whenever you don't want then Transpertview.hidden=YES:

may be it will help.

Dhaval Bhadania
  • 3,090
  • 1
  • 20
  • 35
  • Dhaval Bhadania: Just one question. If I drag in that UIImageView or UIView and perform all of my design & layout inside that, where does it go? Like, if I drag it on top of the calling ViewController in storyboard, it'll cover everything and prevent me from editing the original. If I leave it off to the side, it won't appear in the right place when it is loaded... or is there a way to programatically re-align it? – Erika Electra Oct 22 '13 at 05:42
  • if you want to add programmatically then go with @iPatel answer. – Dhaval Bhadania Oct 22 '13 at 05:47
  • No, ideally I'd like a hybrid of both, like layout my design in Interface Builder since there are a ton of little widgets that need to be carefully placed in the popup, but instantiate a version of the popup in code, if possible. – Erika Electra Oct 22 '13 at 06:20
1

Add #import <QuartzCore/QuartzCore.h> framework in your .m file and use following code

UIWindow* window = [UIApplication sharedApplication].keyWindow;
    self.dimView = [[UIView alloc] initWithFrame:window.bounds];
    self.dimView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:.6];
    self.dimView.userInteractionEnabled = YES;
    [window addSubview:self.dimView];

This above is transparent dimView which size is similar to window.

self.searchTblContainerView = [[UIView alloc] init];
    self.searchTblContainerView.frame = CGRectMake(15, (window.frame.size.height - 300) / 2, 290, 300);
    self.searchTblContainerView.layer.cornerRadius = 15.f;
    self.searchTblContainerView.layer.borderColor = [UIColor blackColor].CGColor; /// set color as per your requirement
    self.searchTblContainerView.layer.borderWidth = 2.f;
    self.searchTblContainerView.alpha = 0.80; /// set as per your requirement 
    self.searchTblContainerView.clipsToBounds = YES;
    [self.dimView addSubview:self.searchTblContainerView];

above self.searchTblContainerView is main view that contain your whole UIControls such like label, textField, Button, etc... and set it as per your requirement.

Set by default hidden property of self.dimView.hidden = YES; and display and hide by following animation like alertView (apple).

Following code for display dimView.

self.searchTblContainerView.transform = CGAffineTransformMakeScale(0.01, 0.01);
        [UIView animateWithDuration:0.30 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            self.searchTblContainerView.transform = CGAffineTransformIdentity;
            self.dimView.hidden = NO;
        } completion:^(BOOL finished){}];

        UIWindow* window = [UIApplication sharedApplication].keyWindow;
        [window bringSubviewToFront:self.dimView];

Following code for hide dimView.

 self.searchTblContainerView.transform = CGAffineTransformIdentity;
    [UIView animateWithDuration:0.30 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        self.searchTblContainerView.transform = CGAffineTransformMakeScale(0.01, 0.01);
    } completion:^(BOOL finished){
        self.dimView.hidden = YES;
    }];

Above code is simple logic, might be useful in your case.

iPatel
  • 46,010
  • 16
  • 115
  • 137
  • iPatel: Thank you for the logic and code. I take it then that I do not need a separate ViewController to handle the dimView? Just subclass UIView and do everything in code with regards to the stuff displayed in the dimView, and let the underlying PhotoCollectionViewController handle displaying, hiding, instantiating the dimView? (i.e. when you say .m file, you mean UnderlyingViewController.m, not DimWindowViewController.m, and there are no segues involved, only showing and hiding). – Erika Electra Oct 22 '13 at 05:24
  • if you dont want to use dimView then it is not important/require to use ,, i just use dimView for you custom view look like alertView. – iPatel Oct 22 '13 at 05:28
  • No, I'm okay with the dimView, just not as confident in designing a UIView without visual guidance. I'm kind of spoiled by Interface Building, so I automatically assumed I needed a ViewController if I were designing the popup in IB and making all my outlets & connections there through ctrl-drag. Not sure how I can make it a UIView instead, without a ViewController. – Erika Electra Oct 22 '13 at 05:36