19

My goal is to keep same coordinates for a UIPopoverController with just changing arrow offset. So basically i have three buttons touching each of them shows up a popover. When presenting this popover it changes position on the screen, but i do not want that. To be more clear look at screenoshots:

enter image description here

enter image description here

enter image description here

gottlieb1878
  • 225
  • 2
  • 7

3 Answers3

15

For my popover I wanted the arrow to be top-left instead of top-center (which is default).

I've managed to get the result below (screenshot) by setting the popoverLayoutMargins property of the UIPopoverController. You can use it to reduce the screen-area used in the internal calculations of the UIPopoverController to determine where to show the popover.

UIPopovercontroller arrow on the left

The code:

// Get the location and size of the control (button that says "Drinks")
CGRect rect = control.frame;

// Set the width to 1, this will put the anchorpoint on the left side
// of the control
rect.size.width = 1;

// Reduce the available screen for the popover by creating a left margin
// The popover controller will assume that left side of the screen starts
// at rect.origin.x
popoverC.popoverLayoutMargins = UIEdgeInsetsMake(0, rect.origin.x, 0, 0);

// Simply present the popover (force arrow direction up)
[popoverC presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];

I think you'll be able to get the desired result by tweaking the above.

Yvo
  • 18,681
  • 11
  • 71
  • 90
  • setting popoverLayoutMargins before displaying works great. thx. – smisiewicz Nov 28 '12 at 21:35
  • Is there a way to place the arrow tip exactly at a point inside the source view. I'm using the whole screen as the source view, so that when there are device orientation changes I just change the source rect, which happens to be of 1x1 units size. The problem is that the arrow is slight to the right of where it's supposed to be. – rraallvv Feb 05 '18 at 16:06
1

You can't do it as-is with Apple's built-in UIPopoverViewController class. But it should be fairly simple and logical to implement your own popover view controller (just some very basic 2D geometry and a bit of digging in UIView's docs).

  • 1
    it can be done with Apple's popovers. If you watch to popovers from table view rows, arrow can follow the row as table is scrolled. So, if the arrow is linked to a rect in a view, you can move that view and the arrow will follow. – Gabriel Jul 05 '12 at 06:20
  • But will the content rect stay at its original position? Won't it follow the arrow in order it to be centered? –  Jul 05 '12 at 06:29
  • No. The popover in my app is large, all the space available up to bottom. The arrow is pointing to a row of the table view in master view of a split view. When eventually a new row appears and table view scrolls, the areow follow the row. – Gabriel Jul 05 '12 at 20:43
1

Yes, you can do that. You have to create an aux view, with alpha=0.0f, and use it to guide the arrow.

For example:

auxView = [[UIView alloc] initWithFrame:firstButton.frame];
auxView.alpha = 0.0 ;
auxView.userInteractionEnabled = NO;
[firstButton.superView addSubview:auxView];
[auxView release];

Ok, now you open popover using that view as arrow's guide.

[thePopoverController presentPopoverFromRect:auxView.bounds inView:auxView
            permitedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];

And now you only have to move the view:

auxView.frame = secondButton.frame;

Use animations for that move if you want.

One more thing, for this kind of arrow to button, I prefer that the arrow touches the button. You can use:

presentPopoverFromRect:CGRectInset(auxView.bounds, 4.0, 4.0)
Gabriel
  • 3,319
  • 1
  • 16
  • 21