2015-05-05 11 views
14

Sto provando a centrare un popover su un pulsante. Non riesco a capire dove potrei sbagliare. Invece che la freccia si trova al centro del pulsante, è al centro della metà della larghezza dello schermo.Popover non centra sul pulsante

@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

risposta

47

Il problema è l'elementare uno di telaio confusa e limiti:

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

No! Vuoi dire che limiti:

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

La ragione è che il sourceRect è dato nello spazio di coordinate del sourceView - che è, se si vuole che sia rect della vista, sono i limiti di questa tesi.

3

Ecco la strada giusta:

@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

C'è un problema in iOS 9. Impostazione l'ancora in uno storyboard:

enter image description here

... comporta la freccia non essere centrati su l'ancora:

enter image description here

Per risolvere, aggiungere questo a prepareForSegue:sender::

// 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

Molto bello answwer. Gli screenshot mi hanno aiutato a capire che era esattamente il problema che avevo. –

+1

Non funziona per me. Sto usando questo codice. lasciare popoverViewController = segue.destinationViewController popoverViewController.modalPresentationStyle = UIModalPresentationStyle.Popover popoverViewController.popoverPresentationController! .delegate = auto se lasciare popoverPresentationController = segue.destinationViewController.popoverPresentationController, sourceView = mittente come?UIView { popoverPresentationController.sourceRect = sourceView.bounds } – Ada

+0

Funziona come un fascino per me! – fivewood

0

Nel mio caso il problema è diverso, il popover viene mostrato per un UIBarButtonItem con una vista personalizzata. Per iOS 11 se si utilizza la visualizzazione personalizzata di UIBarButtonItem, la visualizzazione personalizzata deve essere automatica per il layout.

Con questa categoria è possibile applicare rapidamente i vincoli.

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 

Poi si può fare:

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]; 

Una volta che si applicano i vincoli viene mostrato il popover correttamente sopra la visualizzazione personalizzata, ad esempio, il codice per mostrare un avviso come popover è:

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];