2015-05-05 3 views
14

Ich versuche, ein Popover auf einem Knopf zu zentrieren. Ich kann nicht herausfinden, wo ich vielleicht falsch liege. Anstatt dass sich der Pfeil in der Mitte des Knopfes befindet, ist er um die Hälfte der Bildschirmbreite außermittig.Popover zentriert nicht auf Knopf

@IBAction func buttonClicked(sender: AnyObject){ 
    var popoverViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ServiceOptions") as! ServiceOptionsPopover 
    popoverViewController.delegate = self 
    popoverViewController.modalPresentationStyle = .Popover 
    popoverViewController.preferredContentSize = CGSizeMake(300, 300) 

    let popoverPresentationViewController = popoverViewController.popoverPresentationController 

    popoverPresentationViewController?.permittedArrowDirections = .Up 
    popoverPresentationViewController?.delegate = self 
    popoverPresentationViewController?.sourceView = sender as! UIButton 
    popoverPresentationViewController?.sourceRect = sender.frame 

    presentViewController(popoverViewController, animated: true, completion: nil) 
} 
+0

https://www.dropbox.com/s/99qjhqna07t1iwc/popover.png?dl=0 – user3642915

Antwort

47

Das Problem ist die elementare ein verwirrender Rahmen und Grenzen:

popoverPresentationViewController?.sourceView = sender as! UIButton 
popoverPresentationViewController?.sourceRect = sender.frame 

Nein! Sie meinen Grenzen:

popoverPresentationViewController?.sourceView = sender as! UIButton 
popoverPresentationViewController?.sourceRect = (sender as! UIButton).bounds 

Der Grund dafür ist, dass die sourceRect im Raum-Koordinaten des sourceView gegeben ist - das heißt, wenn Sie es wollen nach Ansicht des rect sein, es ist die Grenzen dieser Ansicht.

3

Hier ist der richtige Weg:

@IBAction func buttonClicked(sender: UIButton){ 
    var popoverViewController = UIViewController() 
    popoverViewController.view.frame = CGRectMake(0,0, 300, 300) 
    popoverViewController.view.backgroundColor = UIColor.redColor() 
    popoverViewController.modalPresentationStyle = .Popover 
    popoverViewController.preferredContentSize = CGSizeMake(300, 300) 

    let popoverPresentationViewController = popoverViewController.popoverPresentationController 

    popoverPresentationViewController?.permittedArrowDirections = .Up 
    popoverPresentationViewController?.sourceView = sender 
    popoverPresentationViewController?.sourceRect = CGRectMake(0, 0, sender.bounds.width,sender.bounds.height) // see this line of code 

    presentViewController(popoverViewController, animated: true, completion: nil) 
} 
36

Es gibt ein Problem in iOS 9. Anker in einem Storyboard einstellen:

enter image description here

... Ergebnisse werden in den Pfeil nicht auf dem Anker zentriert:

enter image description here

Um dies zu beheben, fügen Sie dieses zu prepareForSegue:sender: hinzu:

// Fixes popover anchor centering issue in iOS 9 
if let popoverPresentationController = segue.destinationViewController.popoverPresentationController, sourceView = sender as? UIView { 
    popoverPresentationController.sourceRect = sourceView.bounds 
} 

enter image description here

+1

Sehr nette Antwort. Die Screenshots haben mir gezeigt, dass es genau das Problem war, das ich hatte. –

+1

Nicht für mich arbeiten. Ich benutze diesen Code. lassen popoverViewController = segue.destinationViewController popoverViewController.modalPresentationStyle = UIModalPresentationStyle.Popover popoverViewController.popoverPresentationController! .delegate = Selbst wenn lassen popoverPresentationController = segue.destinationViewController.popoverPresentationController, Sourceview = Absender wie?UIView { popoverPresentationController.sourceRect = sourceView.bounds } – Ada

+0

Funktioniert wie.ein Charme für mich! – fivewood

0

In meinem Fall ist das Problem anders, das Popover wird für ein UIBarButtonItem mit einer benutzerdefinierten Ansicht angezeigt. Wenn Sie für iOS 11 die benutzerdefinierte Ansicht von UIBarButtonItem verwenden, muss die benutzerdefinierte Ansicht automatisch Layout-freundlich sein.

Mit dieser Kategorie können Sie schnell die Einschränkungen anwenden.

UIView + NavigationBar.h

@interface UIView (NavigationBar) 

    - (void)applyNavigationBarConstraints:(CGFloat)width height:(CGFloat)height; 
    - (void)applyNavigationBarConstraintsWithCurrentSize; 

@end 

UIView + NavigationBar.m

#import "UIView+NavigationBar.h" 

@implementation UIView (NavigationBar) 

- (void)applyNavigationBarConstraints:(CGFloat)width height:(CGFloat)height 
{ 
    if (width == 0 || height == 0) { 
     return; 
    } 

    NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:height]; 
    NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:width]; 
    [heightConstraint setActive:TRUE]; 
    [widthConstraint setActive:TRUE]; 
} 

- (void)applyNavigationBarConstraintsWithCurrentSize { 
    [self applyNavigationBarConstraints:self.bounds.size.width height:self.bounds.size.height]; 
} 

@end 

Dann können Sie tun:

UIButton *buttonMenu = [UIButton buttonWithType:UIButtonTypeCustom]; 
[buttonMenu setImage:[UIImage imageNamed:@"menu"] forState:UIControlStateNormal]; 
buttonMenu.frame = CGRectMake(0, 0, 44, 44); 
[buttonMenu addTarget:self action:@selector(showMenu:) forControlEvents:UIControlEventTouchUpInside]; 

//Apply constraints 
[buttonMenu applyNavigationBarConstraintsWithCurrentSize]; 

UIBarButtonItem *menuBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:buttonMenu]; 

Eine Zeit, die Sie anwenden, um die Einschränkungen der popover gezeigt korrekt über der benutzerdefinierten Ansicht, z. B. der Code zum Anzeigen einer Warnung als Popover ist:

UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Menu" message:@"" preferredStyle:UIAlertControllerStyleActionSheet]; 
//Add actions .... 

UIPopoverPresentationController *popController = [controller popoverPresentationController]; 
popController.sourceView = buttonMenu; 
popController.sourceRect = buttonMenu.bounds; 

[self presentViewController:controller animated:YES completion:nil];