弹出窗口不以按钮为中心
Popover doesn't center on button
我正在尝试将弹出框置于按钮的中央。我似乎无法弄清楚我可能哪里出错了。箭头不是位于按钮的中间,而是偏离中心一半的屏幕宽度。
@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)
}
正确的方法是:
@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)
}
问题是混淆框架和边界的初级问题:
popoverPresentationViewController?.sourceView = sender as! UIButton
popoverPresentationViewController?.sourceRect = sender.frame
不!你是说界限:
popoverPresentationViewController?.sourceView = sender as! UIButton
popoverPresentationViewController?.sourceRect = (sender as! UIButton).bounds
原因是 sourceRect
在 sourceView
的坐标 space 中给出 - 也就是说,如果您希望它是视图的矩形,则它是那个观点。
iOS 9. 在故事板中设置锚点:
...导致箭头未以锚点为中心:
要解决,请将此添加到 prepareForSegue:sender:
:
// Fixes popover anchor centering issue in iOS 9
if let popoverPresentationController = segue.destinationViewController.popoverPresentationController, sourceView = sender as? UIView {
popoverPresentationController.sourceRect = sourceView.bounds
}
在我的例子中,问题有所不同,弹出窗口显示为具有自定义视图的 UIBarButtonItem。对于 iOS 11 如果您使用 UIBarButtonItem 的自定义视图,自定义视图需要自动布局友好。
有了这个类别,您可以快速应用约束。
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
那么你可以这样做:
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];
一旦您应用约束,弹出窗口就会在自定义视图上正确显示,例如,将警报显示为弹出窗口的代码是:
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];
我正在尝试将弹出框置于按钮的中央。我似乎无法弄清楚我可能哪里出错了。箭头不是位于按钮的中间,而是偏离中心一半的屏幕宽度。
@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)
}
正确的方法是:
@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)
}
问题是混淆框架和边界的初级问题:
popoverPresentationViewController?.sourceView = sender as! UIButton
popoverPresentationViewController?.sourceRect = sender.frame
不!你是说界限:
popoverPresentationViewController?.sourceView = sender as! UIButton
popoverPresentationViewController?.sourceRect = (sender as! UIButton).bounds
原因是 sourceRect
在 sourceView
的坐标 space 中给出 - 也就是说,如果您希望它是视图的矩形,则它是那个观点。
iOS 9. 在故事板中设置锚点:
...导致箭头未以锚点为中心:
要解决,请将此添加到 prepareForSegue:sender:
:
// Fixes popover anchor centering issue in iOS 9
if let popoverPresentationController = segue.destinationViewController.popoverPresentationController, sourceView = sender as? UIView {
popoverPresentationController.sourceRect = sourceView.bounds
}
在我的例子中,问题有所不同,弹出窗口显示为具有自定义视图的 UIBarButtonItem。对于 iOS 11 如果您使用 UIBarButtonItem 的自定义视图,自定义视图需要自动布局友好。
有了这个类别,您可以快速应用约束。
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
那么你可以这样做:
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];
一旦您应用约束,弹出窗口就会在自定义视图上正确显示,例如,将警报显示为弹出窗口的代码是:
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];