【问题标题】:UIPopover presentFromBarButton off centerUIPopover presentFromBarButton 偏离中心
【发布时间】:2014-08-21 07:14:54
【问题描述】:

我在一个项目中注意到,由于某种原因,右侧栏按钮项上的弹出框的位置似乎偏向右侧。我尝试使用 UIButton 作为自定义视图,然后从该按钮显示弹出框,但如果我实际上为它提供了“居中”值,弹出框似乎会忽略 showFromRect。

这背后的代码很简单:

- (void)viewDidLoad {
    [super viewDidLoad];

     UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"share"] style:UIBarButtonItemStylePlain target:self action:@selector(shareTap:)];

     self.navigationItem.rightBarButtonItem = button;
}

- (void)shareTap:(UIBarButtonItem *)button {
    self.popover = [[UIPopoverController alloc] initWithContentViewController:[[UIViewController alloc] init]];

    [self.popover presentPopoverFromBarButtonItem:button permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

现在,如果我切换到使用内部按钮,如前所述,我会看到类似的行为(注意颜色变化,因此图像显示)。

这个代码还是很简单的:

- (void)viewDidLoad {
    [super viewDidLoad];

    UIButton *innerButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 22, 22)];
    [innerButton setImage:[UIImage imageNamed:@"share"] forState:UIControlStateNormal];
    [innerButton addTarget:self action:@selector(shareTap:) forControlEvents:UIControlEventTouchUpInside];

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:innerButton];;
}

- (void)shareTap:(UIButton *)button {
    self.popover = [[UIPopoverController alloc] initWithContentViewController:[[UIViewController alloc] init]];

//    CGRect bottomCenter = CGRectMake(button.frame.size.width / 2, button.frame.size.height, 1, 1);
    CGRect bottomCenter = CGRectMake(2, button.frame.size.height, 1, 1);

    [self.popover presentPopoverFromRect:bottomCenter inView:button permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

请注意,我没有使用实际的中心,而是使用了任意值 2。如果我使用 1 或 0,弹出框将左对齐。任何大于 1 的都将再次右对齐。

我四处寻找类似的问题,但似乎找不到任何有同样问题的人。任何关于导致这种情况或如何避免这种情况的想法将不胜感激。我唯一能猜到的是,由于它靠近边缘,Apple 做了一些定位巫术来迫使它到达他们想要的位置。问题是右上角按钮似乎是一个非常标准的下拉位置。

编辑:我已经确认长按本机邮件应用程序中的“新消息”图标会发生同样的行为。

编辑 2:我能够与 Apple 确认这是一个问题。在最近的一个版本中(我不记得是哪个,我认为是 9s 之一),他们做到了,所以你可以手动设置它。我相信默认行为仍然是错误的(我已经有一段时间没有尝试过了),但是如果您愿意,可以使用 CGRect 偏移方法使其正常工作。

【问题讨论】:

  • 试试这个 UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(shareTap:)];
  • 您能再解释一下吗?使用系统项目本身并不能修复按钮的位置,在我的编辑中,我提到默认应用程序也会出现问题(邮件),这可能是使用系统图标。

标签: ios uibarbuttonitem uipopovercontroller


【解决方案1】:

您必须指定需要显示弹出框的栏按钮的框架。

以下代码将UIAlertController 显示为条形按钮的弹出框。

    @IBOutlet weak var playerRightBarButton: UIBarButtonItem!

    extension UIBarButtonItem {
       var frame: CGRect? {
        guard let view = self.value(forKey: "view") as? UIView else {
          return nil
      }
      return view.frame
    }
  }

    let alert = UIAlertController(title: "", message: "Sample PopOver", 
    preferredStyle: .actionSheet)
    if alert.responds(to: #selector(getter: popoverPresentationController)) {
            alert.popoverPresentationController?.sourceView = self.view
            alert.popoverPresentationController?.barButtonItem = playerRightBarButton
            alert.popoverPresentationController?.permittedArrowDirections = .up
            if let frame = playerRightBarButton.frame {
                alert.popoverPresentationController?.sourceRect = frame
            }
        }
        self.present(alert, animated: true, completion: nil)

【讨论】:

  • 我不完全确定,但我认为这与我的问题无关。这如何解决箭头位置?您指的是设置什么“框架”?您是说在 UIBarButtonItem 类上添加该扩展方法吗?
  • 该扩展为您提供了 barButton 的框架。当我们设置需要显示弹出框的框架时,它会相应地居中。我提供了一个在 iPad 中显示为 popOver 的 alertController 示例。
【解决方案2】:

这里有一种方法:不要使用UIBarButtonSystemItem,而是使用带有自定义视图的UIBarButtonItem。只需将UIButton 拖入UINavigationBar 即可获得带有嵌入UIButtonUIBarButtonItem,它显示为UIBarButtonItem 的customView。

@IBAction func didTapActionButton(_ sender: Any) {
    if let vc = self.storyboard?.instantiateViewController(withIdentifier: "myPopover") {
        vc.modalPresentationStyle = .popover
        guard let innerView = actionButton.customView else {
            // Unexpected missing custom view
            return
        }

        vc.popoverPresentationController?.sourceView = navigationController?.navigationBar
        vc.popoverPresentationController?.sourceRect = innerView.frame
        self.present(vc, animated: true, completion: nil)
    }
}

【讨论】:

  • 我想你可能会注意到这是在 iOS 9 之后修复的。我在帖子的开头提到,即使 UIButton 也不起作用,但后来(在编辑中)Apple 更新了它以便您可以使用 UIButton 修复定位。
  • 我遇到了你最初在 iOS 10 上的一个项目中描述的弹出箭头偏移问题,这对我来说是修复 - 我猜你的意思是这种方法在 iOS 上不起作用9 存在错误的地方。我没试过。
猜你喜欢
  • 1970-01-01
  • 2021-11-02
  • 1970-01-01
  • 2011-03-05
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
  • 1970-01-01
相关资源
最近更新 更多