UIPopoverPresentationController将弹出视图呈现为全屏显示

44

我尝试使用UIPopoverPresentationController来显示一个不占据整个屏幕的popover。我已经按照许多不同的教程进行了尝试,但仍然没有成功。

这是我的代码。它正确地实例化了ViewController,但它占据了整个屏幕而不是像我在preferredContentSize中定义的那样只占用较小的屏幕。

func showPopover() {
    let vc = self.storyboard?.instantiateViewControllerWithIdentifier("PopupTimePickerViewController") as PopupTimePickerViewController
    vc.modalPresentationStyle = .Popover
    vc.preferredContentSize = CGSizeMake(200, 100)

    if let presentationController = vc.popoverPresentationController {
        presentationController.delegate = self
        presentationController.permittedArrowDirections = .Up
        presentationController.sourceView = self.view
        presentationController.sourceRect = CGRectMake(0, 0, 50, 50)

        self.presentViewController(vc, animated: true, completion: nil)
    }
}

已于2016年9月27日更新并提供正确答案

func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
    return .none
}

@gabbler 不行,只能在模拟器上测试。没有 iPhone 可以测试。 - The Nomad
请尝试答案。不要忘记实现 adaptivePresentationStyleForPresentationController 方法。 - gabbler
对我来说,问题在于通过“PerformSegue”调用PopoverViewController时,它总是保持全屏状态。删除故事板segue并手动组装并通过presentViewController显示解决了这个问题。 - Alexandre
更新救了我。卡了6个多小时。 - MingMan
6个回答

44

为了呈现一个弹出视图,在iPhone中,您应该添加以下内容。

func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!) -> UIModalPresentationStyle {
    // Return no adaptive presentation style, use default presentation behaviour
    return .None
}

2
你把这个加到哪里?是加到 Popover 的视图控制器里吗? - Noah
1
@Noah,对于呈现弹出窗口的视图控制器,self.presentViewController(vc, animated: true, completion: nil),其中的控制器 self 表示当前视图控制器。 - gabbler
9
在Swift 4中,这段代码不会出错,但也无法解决问题。稍作修改:func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle { return UIModalPresentationStyle.none }这将修复该问题。 - Cannoliopsida
1
是的,为了调用它,你需要将调用视图控制器设置为弹出窗口 presentationController 的委托,就像其他答案中所解释的那样。然后,你可以查看相应签名的协议定义。如果你正确地设置了委托,Xcode 应该会自动完成正确的签名。 - Victor Engel

20

对于Swift3/IOS10,似乎我们需要做一些类似于以下的事情:

func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle
{
    return .none
}

如果有人像我一样在迁移到swift3/IOS10时遇到了这个问题,请参考我的回答。


7

在处理 iPhone 的 Swift3+/IOS10+ 时:

你必须在以下位置添加 UIPopoverPresentationControllerDelegate 代理:

class YourClass:  UIViewController, UIPopoverPresentationControllerDelegate { ...

然后在这个同样的父类中实现以下方法(将显示弹出窗口)。
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle
{
    return .none
}

然后设置以下弹出框配置:

myPopover.modalPresentationStyle = .popover
myPopover.popoverPresentationController?.sourceRect = VIEWTOPOINTTHEARROW.frame
myPopover.popoverPresentationController?.sourceView = self.view
myPopover.popoverPresentationController?.delegate = self

您可以为弹出框类设置一些配置。
 class MyPopover: UIViewController {

 override func viewDidLoad() {
    super.viewDidLoad()
    //popover size
    self.preferredContentSize = CGSize(width: 320, height: 200) 
    //sets the arrow of the popover to same color of background
    self.popoverPresentationController?.backgroundColor = self.view.backgroundColor
   }

 }

4
接受的答案是正确的。为了完整起见,请参阅苹果文档中的将呈现的视图控制器调整到新样式

使用委托的adaptivePresentationStyleForPresentationController:方法指定与默认不同的演示文稿样式。在过渡到紧凑环境时,支持的样式仅有两种全屏样式或UIModalPresentationNone。返回UIModalPresentationNone告诉表示控制器忽略紧凑环境并继续使用先前的演示文稿样式。在弹出窗口的情况下,忽略更改会使您在所有设备上获得与iPad相似的弹出窗口行为。

确保满足在弹出窗口中显示视图控制器所需的配置:

将呈现的视图控制器的模态呈现样式设置为UIModalPresentationPopover后,配置以下与弹出窗口相关的属性:

  • 将您的视图控制器的preferredContentSize属性设置为所需的大小。
  • 使用相关联的UIPopoverPresentationController对象设置弹出窗口锚点,该对象可从视图控制器的popoverPresentationController属性访问。
  • 仅设置以下内容之一:
    • barButtonItem属性设置为一个工具栏按钮。
    • sourceViewsourceRect属性设置为您的某个视图中的特定区域。

0

iOS 12 / Swift 4

还有一种可能是在iPhone上将弹出窗口显示为全屏,而在iPad上则显示为弹出窗口。

只需返回.popover以获取adaptivePresentationStyle()

func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
    return .popover
}

并像 @mourodrigo 一样设置弹出窗口配置:

dialog.modalPresentationStyle = .popover
dialog.popoverPresentationController?.delegate = self
dialog.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)
dialog.popoverPresentationController?.sourceView = view
dialog.popoverPresentationController?.sourceRect = view.frame

0

Objective-C 版本:

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
    return UIModalPresentationNone;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接