4
votes

I've got a UIPopoverController which I've been using for awhile. I'm updating my code for iOS 7 now and when I resize the popover it suddenly moves across the screen which makes for a very bad user experience.

When I'm in portrait orientation, it doesn't happen. I tap to open the popover, then I tap the button which causes the popover to expand and everything is fine. However, if I switch to Landscape orientation and do the same thing, when I tap the button to expand the popover, then it slides over to another location.

Here is a video showing what I'm talking about: https://vimeo.com/75632364

This the code that runs when the user taps the button that causes the resize of the popover:

- (IBAction) touchedButtonPayDownLoan:(id)sender {

    UIView *payOffView = nil;
    if ([self.liability isBankLoan]) {
        payOffView = self.viewPayoffBank;
    } else {
        payOffView = self.viewPayoffOther;
    }

    CGRect loanFrame = payOffView.frame;
    loanFrame.origin.y = self.toolbar.frame.origin.y;
    payOffView.frame = loanFrame;
    [self.view addSubview:payOffView];
    [self.view bringSubviewToFront:self.toolbar];

    [UIView beginAnimations:@"Show Payoff View" context:nil];

    NSMutableArray *items = [[self.toolbar items] mutableCopy];
    [items removeLastObject];
    [items addObject:self.barButtonFinish];
    self.toolbar.items = items;

    // -------- RELEVANT BITS HERE ---------
    CGRect frame = self.view.frame;
    frame.size.height += payOffView.frame.size.height;
    self.view.frame = frame;
    self.preferredContentSize = frame.size;
    // -------- RELEVANT BITS HERE ---------

    [UIView commitAnimations];

}

I don't want the popover to jump positions, because that will annoy the user. Any ideas?

5

5 Answers

4
votes

I've run into a similar issue, and I found that the movements of the popover are caused by the fact that the layout manager thinks that the popover with new size would not fit at last position, or would look better at new one - you are most likely creating the popover with

permittedArrowDirections = UIPopoverArrowDirectionAny

what's confusing is that although the popover moves to a new position the arrow doesn't get redrawn.

On my end, I've solved the issue by explicitly setting permittedArrowDirections to one value (UP or DOWN) and the resizes no longer make my popover move around.

Hope this helps.

1
votes

When the popover is visible and you want to change its size, you should use:

-[UIPopover setPopoverContentSize:animated:]

You shouldn't change the frame of the controller directly.

0
votes

At first glance, your code looks fine. I haven't used beginAnimations:context:, so I checked the UIView documentation for it, and it includes this comment:

Use of this method is discouraged in iOS 4.0 and later. You should use the block-based animation methods to specify your animations instead.

So I recommend changing your code to use the block-based animation methods, e.g. animateWithDuration:animations: and see if your popover still moves unexpectedly.

0
votes

Thanks to the answer by @PeterSarnowski I was able to stop my popover from moving around in iOS7:

[myPopoverController presentPopoverFromRect:view.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];

I wonder if this workaround is necessary because Apple was (and maybe still is?) considering changing popover behavior in iOS7:

But apparently the documentation is not accurate at the present time. iOS 7 - UIPopoverController : deprecated arrows?

0
votes

You should take a look at the new popoverController:willRepositionPopoverToRect:inView: method for UIPopoverControllerDelegate in iOS 7. You can adjust the position of the UIPopover in there.

From Apple's documentation:

For popovers that were presented using the presentPopoverFromRect:inView:permittedArrowDirections:animated: method, the popover controller calls this method when the interface orientation changes. Your delegate can use this method to adjust the proposed position of the popover.