UIPopOver and orientation change

时光总嘲笑我的痴心妄想 提交于 2019-12-04 08:47:49

问题


In my app I have 3 UIPopOvers. They appear when user taps buttons in the toolbar. I need to make the popovers appear in the correct place when user rotates iPad if the popover is already opened (like the -willAnimateRotationToInterfaceOrientation:).

How can I do it?

Thanks in advance!


回答1:


In iOS 7.0 and later, it can be done by implementing following method available in UIPopoverControllerDelegate:

(void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView **)view

For popovers that were presented using the presentPopoverFromRect method, the popover controller calls this method when the interface orientation changes.




回答2:


The only solution I've found so far is just closing the popover when the device is rotated/




回答3:


Here is a code fragment from one of my projects. Basically, if the popover is showing, you present the popover again in the method didRotateFromInterfaceOrientation:, which is sent to the view controller after the user interface rotation has taken place. (The willRotate... and willAnimateRotation... methods are called before the rotation has taken place, so it is the wrong place for the presentPopover... method call.)

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
  // if the popover is showing, adjust its position after the re-orientation by presenting it again:
  if (self.myPopoverController != nil)  // if the popover is showing (replace with your own test if you wish)
  {
    [self.myPopoverController presentPopoverFromRect:attachmentRect
                                              inView:myView
                            permittedArrowDirections:UIPopoverArrowDirectionUp
                                            animated:YES];
  }    
}

In the above, self.myPopoverController is a property of my view controller where I store a reference to the popover when it is created. When I dismiss and discard the popover under normal circumstances, I take care to set this property to nil, so I can check it for 'non-nil'ness to decide whether or not the popover is being shown.

Note, however, that you don't need to dismiss the popover before the rotation takes place. Just present the same popover again. (This is where keeping a reference to the popover comes in handy.)

In your case, where the popover emanates from a toolbar button, you would use something like the following instead:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
  // if the popover is showing, adjust its position after the re-orientation by presenting it again:
  if (self.myPopoverController != nil)  // if the popover is showing (replace with your own test if you wish)
  {
    [self.myPopoverController presentPopoverFromBarButtonItem:barButtonItem
                                     permittedArrowDirections:UIPopoverArrowDirectionAny
                                                     animated:YES];
  }    
}



回答4:


If you simply use the presentPopoverFromBarButtonItem method to present your popover then the popover will automatically move to the correct position for the new button position when the device is rotated.




回答5:


Are you calling presentPopoverFromBarButtonItem or FromRect? Are you making any changes to the BarButtonItem on rotate?

Apple's documentation specifically states you need to manage position on rotation for FromRect or if you modify the bar button item. See fourth paragraph in http://developer.apple.com/library/ios/#documentation/uikit/reference/UIPopoverController_class/Reference/Reference.html




回答6:


I've run into this same issue a couple of times. I typically just make a method to show the popover centered like this:

- (void) showPopoverForSize:(CGSize) size center:(CGPoint) center {
   CGFloat width = size.width;
    CGFloat height = size.height;
    CGFloat x = center.x - width / 2;
    CGFloat y = center.y - height / 2;
    CGRect frame = CGRectMake(x, y, width, height);
    popover.popoverContentSize = frame.size;

    [popover presentPopoverFromRect:frame inView:self.view permittedArrowDirections:0 animated:YES];
}

Then on didRotate I do:

- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
    if (popover.isPopoverVisible)
        [self showPopoverForSize:popover.popoverContentSize center:self.view.center];
}

This will put the popover in the center for any orientation.




回答7:


At the beginning of the change of orientation dismiss the popover, and after the change of orientation is completed it again and it changes present its position on the screen:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
            [_popover dismissPopoverAnimated:YES];
        }
    }

    - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
    {
        if (_popover) {
            [_popover presentPopoverFromRect:frameRect
                                                      inView:self.view
                                    permittedArrowDirections:UIPopoverArrowDirectionUp
                                                    animated:YES];
        }    
    }



回答8:


Performing popover function:

func presentPopover() {
    self.popoverFlag = true
    //Presenting PopOver code goes here
    // ...
}

Dismissing presented popover on changing orientation:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

        if self.isKindOfClass(ViewController) && self.popoverFlag{
            guard self.presentedViewController != nil else { return }
            dispatch_async(dispatch_get_main_queue()) {
                self.presentedViewController!.dismissViewControllerAnimated(true, completion: nil)
            }
        }
    }

Presenting popover again:

func popoverPresentationController(popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverToRect rect: UnsafeMutablePointer<CGRect>, inView view: AutoreleasingUnsafeMutablePointer<UIView?>) {
    self.presentPopover()
}



回答9:


You should use UIPopoverPresentationControllerDelegate method:

func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverTo rect: UnsafeMutablePointer<CGRect>, in view: AutoreleasingUnsafeMutablePointer<UIView>)

and update the rect value.

See @Hugo Alonso's answer here



来源:https://stackoverflow.com/questions/3008477/uipopover-and-orientation-change

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!