如何在iOS 8中正确呈现popover

时间:2014-07-08 15:24:54

标签: ios swift uipopovercontroller ios8 uipopover

我正在尝试将UIPopoverView添加到我的Swift iOS 8应用程序中,但我无法访问PopoverContentSize属性,因为popover没有显示正确的形状。我的代码:

var popover: UIPopoverController? = nil 

    func addCategory() {

    var newCategory = storyboard.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
    var nav = UINavigationController(rootViewController: newCategory)
    popover = UIPopoverController(contentViewController: nav)
    popover!.setPopoverContentSize(CGSizeMake(550, 600), animated: true)
    popover!.delegate = self
    popover!.presentPopoverFromBarButtonItem(self.navigationItem.rightBarButtonItem, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
}

输出:

enter image description here

当我通过UIPopoverPresentationController做同样的事情时,我仍然没有完成它。这是我的代码:

func addCategory() {

    var popoverContent = self.storyboard.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
    var nav = UINavigationController(rootViewController: popoverContent)
    nav.modalPresentationStyle = UIModalPresentationStyle.Popover
    var popover = nav.popoverPresentationController as UIPopoverPresentationController
    popover.delegate = self
    popover.popoverContentSize = CGSizeMake(1000, 300)
    popover.sourceView = self.view
    popover.sourceRect = CGRectMake(100,100,0,0)

    self.presentViewController(nav, animated: true, completion: nil)

}

我得到完全相同的输出。

如何自定义弹出窗口的大小?任何帮助将非常感谢!

13 个答案:

答案 0 :(得分:141)

好吧,一位室友看了看它并想出来了:

 func addCategory() {

    var popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
    var nav = UINavigationController(rootViewController: popoverContent)
    nav.modalPresentationStyle = UIModalPresentationStyle.Popover
    var popover = nav.popoverPresentationController
    popoverContent.preferredContentSize = CGSizeMake(500,600)
    popover.delegate = self
    popover.sourceView = self.view
    popover.sourceRect = CGRectMake(100,100,0,0)

    self.presentViewController(nav, animated: true, completion: nil)

}

就是这样。

你不再与popover本身交谈,你可以通过调用属性preferredContentSize

与内部的视图控制器交谈以设置内容大小

答案 1 :(得分:48)

实际上它比这简单得多。在故事板中,您应该将要用作popover的viewcontroller设置为像往常一样为它创建一个viewcontroller类。从要打开弹出窗口的对象中创建如下所示的segue,在这种情况下,UIBarButton命名为" Config"。

enter image description here

在"母亲控制器"实现UIPopoverPresentationControllerDelegate和委托方法:

func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
    //do som stuff from the popover
}

像这样覆盖prepareForSeque方法:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     //segue for the popover configuration window
    if segue.identifier == "yourSegueIdentifierForPopOver" {
        if let controller = segue.destinationViewController as? UIViewController {
            controller.popoverPresentationController!.delegate = self
            controller.preferredContentSize = CGSize(width: 320, height: 186)
        }
    }
}

你已经完成了。现在,您可以将弹出窗口视图视为任何其他视图,即。添加字段,什么不是!您可以使用popoverPresentationController.presentedViewController中的UIPopoverPresentationController方法来掌握内容控制器。

同样在iPhone上你必须覆盖

func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {

        return UIModalPresentationStyle.none
    } 

答案 2 :(得分:28)

我找到了一个完整的示例,说明如何使这一切全部工作,以便始终显示一个弹出框,无论设备/方向https://github.com/frogcjn/AdaptivePopover_iOS8_Swift

关键是实现UIAdaptivePresentationControllerDelegate

func adaptivePresentationStyleForPresentationController(PC: UIPresentationController!) -> UIModalPresentationStyle {
    // This *forces* a popover to be displayed on the iPhone
    return .None
}

然后扩展上面的例子(来自Imagine Digital):

nav.popoverPresentationController!.delegate = implOfUIAPCDelegate

答案 3 :(得分:25)

Swift 2.0

好吧我锻炼了。看一看。在StoryBoard中制作了一个ViewController。与PopOverViewController类相关联。

import UIKit

class PopOverViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()    
        self.preferredContentSize = CGSizeMake(200, 200)    
        self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "dismiss:")    
    }    
    func dismiss(sender: AnyObject) {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
}      

请参阅ViewController:

//  ViewController.swift

import UIKit

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate
{
    func showPopover(base: UIView)
    {
        if let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("popover") as? PopOverViewController {    

            let navController = UINavigationController(rootViewController: viewController)
            navController.modalPresentationStyle = .Popover

            if let pctrl = navController.popoverPresentationController {
                pctrl.delegate = self

                pctrl.sourceView = base
                pctrl.sourceRect = base.bounds

                self.presentViewController(navController, animated: true, completion: nil)
            }
        }
    }    
    override func viewDidLoad(){
        super.viewDidLoad()
    }    
    @IBAction func onShow(sender: UIButton)
    {
        self.showPopover(sender)
    }    
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
        return .None
    }
}  

注意:func showPopover(base:UIView)方法应放在ViewDidLoad之前。希望它有所帮助!

答案 4 :(得分:13)

在iOS9中,UIPopoverController被折旧。因此可以在iOS9.x以上的Objective-C版本中使用以下代码,

<div id="box" style="display:none"></div>
    <script type="text/javascript">
         document.getElementById("box").style.display = "block";
    </script>

答案 5 :(得分:7)

这里我将“Joris416”Swift代码转换为Objective-c,

-(void) popoverstart
{
    ViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"PopoverView"];
    UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:controller];
    nav.modalPresentationStyle = UIModalPresentationPopover;
    UIPopoverPresentationController *popover = nav.popoverPresentationController;
    controller.preferredContentSize = CGSizeMake(300, 200);
    popover.delegate = self;
    popover.sourceView = self.view;
    popover.sourceRect = CGRectMake(100, 100, 0, 0);
    popover.permittedArrowDirections = UIPopoverArrowDirectionAny;
    [self presentViewController:nav animated:YES completion:nil];
}

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

记得要添加 UIPopoverPresentationControllerDelegate, UIAdaptivePresentationControllerDelegate

答案 6 :(得分:4)

最好在iOS8 Day-by-Day blog

上解释

简而言之,一旦您将UIViewController的modalPresentationStyle设置为.Popover,您就可以通过控制器的popoverPresentationController属性获取UIPopoverPresentationClass(一个新的iOS8类)。

答案 7 :(得分:3)

xcode 9.1 / swift 4的两分钱。

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {

    override func viewDidLoad(){
        super.viewDidLoad()

        let when = DispatchTime.now() + 0.5

        DispatchQueue.main.asyncAfter(deadline: when, execute: { () -> Void in
            // to test after 05.secs... :)
            self.showPopover(base: self.view)

        })

}


func showPopover(base: UIView) {
    if let viewController = self.storyboard?.instantiateViewController(withIdentifier: "popover") as? PopOverViewController {

        let navController = UINavigationController(rootViewController: viewController)
        navController.modalPresentationStyle = .popover

        if let pctrl = navController.popoverPresentationController {
            pctrl.delegate = self

            pctrl.sourceView = base
            pctrl.sourceRect = base.bounds

            self.present(navController, animated: true, completion: nil)
        }
    }
}


@IBAction func onShow(sender: UIButton){
    self.showPopover(base: sender)
}

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

并试验:

func adaptivePresentationStyle ...

    return .popover

或:         return .pageSheet .... 等等..

答案 8 :(得分:2)

我在上面快速回答了Imagine Digitals的Objective-C版本。我不认为我错过任何东西,因为它似乎在初步测试下工作,如果你发现了一些让我知道的东西,我会更新它

-(void) presentPopover
{
    YourViewController* popoverContent = [[YourViewController alloc] init]; //this will be a subclass of UIViewController
    UINavigationController* nav =  [[UINavigationController alloc] initWithRootViewController:popoverContent];
    nav.modalPresentationStyle = UIModalPresentationPopover;
    UIPopoverPresentationController* popover = nav.popoverPresentationController;
    popoverContent.preferredContentSize = CGSizeMake(500,600);
    popover.delegate = self;
    popover.sourceRect = CGRectMake(100,100,0,0); //I actually used popover.barButtonItem = self.myBarButton;

    [self presentViewController:nav animated:YES completion:nil];
}

答案 9 :(得分:2)

在Viewcontroller中实现UIAdaptivePresentationControllerDelegate。 然后添加:

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

答案 10 :(得分:0)

以下内容提供了有关如何配置和显示弹出窗口的非常全面的指南。 https://www.appcoda.com/presentation-controllers-tutorial/

总而言之,一个可行的实现(对 Swift 4.2 的原始文章语法进行了一些更新),然后从其他地方调用,将类似于以下内容:

func showPopover(ofViewController popoverViewController: UIViewController, originView: UIView) {
    popoverViewController.modalPresentationStyle = UIModalPresentationStyle.popover
    if let popoverController = popoverViewController.popoverPresentationController {
        popoverController.delegate = self
        popoverController.sourceView = originView
        popoverController.sourceRect = originView.bounds
        popoverController.permittedArrowDirections = UIPopoverArrowDirection.any
    }
    self.present(popoverViewController, animated: true)
}

@mmc的答案中已经涵盖了很多内容,但是本文有助于解释其中使用的某些代码元素,并说明如何扩展它。

它还提供了有关使用委派处理iPhone与iPad的演示样式以及允许在弹出窗口全屏显示时将其关闭的更多详细信息。再次更新为 Swift 4.2

func adaptivePresentationStyle(for: UIPresentationController) -> UIModalPresentationStyle {
    //return UIModalPresentationStyle.fullScreen
    return UIModalPresentationStyle.none
}

func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
    if traitCollection.horizontalSizeClass == .compact {
        return UIModalPresentationStyle.none
        //return UIModalPresentationStyle.fullScreen
    }
    //return UIModalPresentationStyle.fullScreen
    return UIModalPresentationStyle.none
}

func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
    switch style {
    case .fullScreen:
        let navigationController = UINavigationController(rootViewController: controller.presentedViewController)
        let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.done, target: self, action: #selector(doneWithPopover))
        navigationController.topViewController?.navigationItem.rightBarButtonItem = doneButton
        return navigationController
    default:
        return controller.presentedViewController
    }
}

// As of Swift 4, functions used in selectors must be declared as @objc
@objc private func doneWithPopover() {
    self.dismiss(animated: true, completion: nil)
}

希望这会有所帮助。

答案 11 :(得分:0)

对于那些想学习的人!

我为那些想要研究和使用Popover视图的人创建了一个开源项目。您可以在此处找到该项目。 https://github.com/tryWabbit/KTListPopup

KTListNewResize

答案 12 :(得分:0)

 var popoverContent = (self.storyboard?.instantiateViewController(withIdentifier: "WhatsNewViewController"))! as UIViewController
        var nav = UINavigationController(rootViewController: popoverContent)
    nav.modalPresentationStyle = UIModalPresentationStyle.popover
        var popover = nav.popoverPresentationController
        popoverContent.preferredContentSize = CGSize(width: 500, height: 100)
        popover?.delegate = self
        popover?.sourceView = self.view
        popover?.sourceRect = CGRectMake(100,100,0,0)

    self.present(nav, animated: true, completion: nil)