Show a custom popover view within your iPad App

The possibility to show popover views (modal or non modal) is a really cool thing within the new iPhone OS 3.2. It allows you to display important information, request some input from the user or present some kind of navigation structure. Anyway, it depends on your application but it helps to focus the user on your main content and to avoid too many context (or better: view layout) changes.

Now I am going to give you just a quick example of how we can display a customized popover view within our application. First of all I want to present a simple popover view when a given toolbar button was pressed. The class UIPopoverController offers the functionality to show a popover with any given view controller.

We are also able to limit the popover’s view size with the new property contentSizeForViewInPopover in all UIViewController classes. If you don’t customize this property, the popover will be shown in its default width of 320 px and in full screen height.

After initialization of your UIPopoverController instance you can call the method presentPopoverFromBarButtonItem: permittedArrowDirections: animated:. The first parameter is used to locate the control which creates the popover view. The second parameter permittedArrowDirections allows you to restrict the direction of the shown arrow of the popover. To support all orientations and layout changes, UIPopoverArrowDirectionAny is the best way to go.

-(void) toolbarAction:(id)sender {
   if([self.popoverController isPopoverVisible])
   {
      //close the popover view if toolbar button was touched
      //again and popover is already visible
      //Thanks to @chrisonhismac
 
      [self.popoverController dismissPopoverAnimated:YES];
      return;
   }
 
   //build our custom popover view
   UIViewController* popoverContent = [[UIViewController alloc]
                              init];
   UIView* popoverView = [[UIView alloc]
                        initWithFrame:CGRectMake(0, 0, 300, 400)];
   popoverView.backgroundColor = [UIColor blueColor];
   popoverContent.view = popoverView;
 
   //resize the popover view shown
   //in the current view to the view's size
   popoverContent.contentSizeForViewInPopover =
                              CGSizeMake(300, 400);
 
   //create a popover controller
   self.popoverController = [[UIPopoverController alloc]
               initWithContentViewController:popoverContent];
 
   //present the popover view non-modal with a
   //refrence to the toolbar button which was pressed
   [self.popoverController presentPopoverFromBarButtonItem:sender
               permittedArrowDirections:UIPopoverArrowDirectionUp
               animated:YES];
 
   //release the popover content
   [popoverView release];
   [popoverContent release];
}

In my example application I get the following screen:

So, while showing popover views from toolbar items is very common, it is also often necessary to show popovers when interacting with other UI controls within your screen. Another example will show a popover view triggered from a standard button within my main content view.

I placed a button called popoverButton which performs the following method when activated. This time we use the method presentPopoverFromRect and use the button’s frame as source for the direction of the popover’s arrow. The popover implementation is very sophisticated and places the popover so it fits best at the current screen.

-(void) buttonAction:(id)sender {
   //build our custom popover view
   UIViewController* popoverContent = [[UIViewController alloc]
                  init];
   UIView* popoverView = [[UIView alloc]
                  initWithFrame:CGRectMake(0, 0, 200, 300)];
   popoverView.backgroundColor = [UIColor greenColor];
   popoverContent.view = popoverView;
 
   //resize the popover view shown
   //in the current view to the view's size
   popoverContent.contentSizeForViewInPopover =
                  CGSizeMake(200, 300);
 
   //create a popover controller
   self.popoverController = [[UIPopoverController alloc]
               initWithContentViewController:popoverContent];
 
   //present the popover view non-modal with a
   //refrence to the button pressed within the current view
   [self.popoverController presentPopoverFromRect:popoverButton.frame
               inView:self.view
               permittedArrowDirections:UIPopoverArrowDirectionAny
               animated:YES];
 
   //release the popover content
   [popoverView release];
   [popoverContent release];
}

Using this code will create another popover which will look as shown in the picture below:

I really like popovers and also the possibility to show them in a modal manner. It is recommended to use modal popover views very rarely because the user’s focus gets lost from the main content. Use them only when it is really necessary and some kind of mandatory input is needed (i.e. accepting terms of use).

You will find the source code of this example at my github repository. The project is called PopoverView.

Cheers,
Andreas

16 Responses to “Show a custom popover view within your iPad App”


  • Great work Andreas,
    I am just looking for same :)

  • Hi,

    Are the screen shots above from a standard split-view application? I'd like to split my master list into sections but I'm not sure how to to do it.

    Thanks,

    Jared

  • Could you also show how to add content to the popover view?

    I would like to add 2 buttons that do stuff.

    Thank You

    • Hi John,

      the popover view is like every view you use within the SDK. So just create a new instance of UIButton, set its target and frame and add it as a subview of your popover view.

      Example:

      UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
      button.frame = CGRectMake(20, 20, 150, 40);
      [button setTitle:@"A button" forState:UIControlStateNormal];
      [button addTarget:self action:@selector(yourAction:) forControlEvents:UIControlEventTouchUpInside];
      [popoverView addSubview:button];

      Cheers,
      Andreas

  • Hey Andreas,
    cool stuff!

    I would also be very interested in how to present a UIPickerView inside the popover!
    Could you please post a few lines on this topic?

    Thank you

    • Hi,

      the simplest way is to design your popover view and its content within Interface Builder first. After that create your view controller as usual and show it as a popover view. You can place your UIPickerView in there and also set its delegate and data source.

      I added a simple example to the source code within the git repository (http://github.com/anka/bw_examples).

      Cheers,
      Andreas

  • hello!, excellent post! actually i have a question, i'm building an app. there is a popover with a uiimagepicker, i need the user to pick an image and to show it in an imageview in the main view.
    i make it to show the image picker in a popover but nothing happens when I tap on an image, can you help me with that? i'm kind of noob,and sorry for my bad english!

  • Thank you so much! I was having so much trouble with this. You made this easy to understand. I appreciate that you would share this with us all.

  • Thanyou for the code! It works well with the exception of the Toolbar button. It opens the PopOver just fine but doesnt dismiss. I fixed it using this code

    //method which gets called when button at toolbar was activated
    - (void) toolbarAction:(id) sender {
    if ([self.popoverController isPopoverVisible]) {
    //using the setters and getters "goes thru the proper channels" when accessing objects
    [self.popoverController dismissPopoverAnimated:YES];
    } else {
    //build our custom popover view
    UIViewController* popoverContent = [[UIViewController alloc]
    init];
    UIView* popoverView = [[UIView alloc]
    initWithFrame:CGRectMake(0, 0, 300, 400)];
    popoverView.backgroundColor = [UIColor whiteColor];
    popoverContent.view = popoverView;

    //resize the popover view shown
    //in the current view to the view's size
    popoverContent.contentSizeForViewInPopover = CGSizeMake(300, 400);

    //create a popover controller
    self.popoverController = [[UIPopoverController alloc]
    initWithContentViewController:popoverContent];

    //present the popover view non-modal with a
    //refrence to the toolbar button which was pressed
    [self.popoverController presentPopoverFromBarButtonItem:sender
    permittedArrowDirections:UIPopoverArrowDirectionUp
    animated:YES];
    //release the popover content

    [popoverView release];
    [popoverContent release];

    }

    }

    • Hi,
      thanks for the improvement. Its true, if you touch the toolbar button once again it doesn't dismiss instead it opens another popover view. I included your recommendation to the example code.

      Thanks,
      Andreas

  • Hi Andreas, I included this in an App I made and Apple accepted it (as above, thanks again) and a week ago they sent me an e-mail asking me to change something. I totally missed this. When inside a detail view of the split view (rotated to landscape) or when in portrait view everything is fine, but if rotated the popover re-appears at the original coordinates(making it out of position). I have tried for over a week and am stumped (I am new to this and it is a hobby). Any suggestions? If you want to view what I am talking about, you can view my App (it's free) by going to http://www.bickfordperformance.com/iPad/ and look at link on the bottom of the page. The popovers are used in the 'Meet our Service Staff'. Thanks again for sharing with us!

  • Thanks for the tutorial, I'm wondering how I can add a tableView to the popover view?

    Something that will look similar to the default split view popover, but will have a popover in both landscape and portrait views (rather than the split view in landscape).

    Thanks!

  • Excellent Tutorial. Thanks heaps.

  • Thanks! it saved me a lot of work :)

Leave a Reply