ios 如何快速居中 popoverview

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31759615/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 07:05:54  来源:igfitidea点击:

how to center a popoverview in swift

iosswiftmodal-dialoguipopovercontroller

提问by mcfly soft

I have the following code to show a popoverview (dialog) without an arrow, which works fine. The only problem is, that the dialog is shown in the top left (IPad). I would like to center the view on the screen.

我有以下代码来显示没有箭头的 popoverview(对话框),效果很好。唯一的问题是,对话框显示在左上角(iPad)。我想将视图集中在屏幕上。

What to change or add in my following code ? :

在我的以下代码中更改或添加什么?:

func show_help(){


    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let controller = storyboard.instantiateViewControllerWithIdentifier("Help") as! UIViewController

    controller.modalPresentationStyle = UIModalPresentationStyle.popover

    let popoverPresentationController = controller.popoverPresentationController

    // result is an optional (but should not be nil if modalPresentationStyle is popover)
    if let _popoverPresentationController = popoverPresentationController {

        // set the view from which to pop up
        _popoverPresentationController.sourceView = self.view;
        _popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirection.allZeros;
        // present (id iPhone it is a modal automatic full screen)
        self.presentViewController(controller, animated: true, completion: nil)
    }

}

Additional Infos

附加信息

enter image description here

在此处输入图片说明

In my view, which is linked to my viewcontroller I set the preffered size like this:

在我看来,它链接到我的视图控制器,我设置了这样的首选大小:

override func viewDidLoad() {
        let dialogheigth:CGFloat = self.view.frame.height * 0.5;
        let dialogwidth:CGFloat = self.view.frame.width * 0.5;
        self.preferredContentSize = CGSizeMake(dialogwidth,dialogheigth);
}

回答by Istvan

You need to provide the source rect for the popover.

您需要为弹出框提供源矩形。

From the apple documentation: the source rect is the rectangle in the specified view in which to anchor the popover. Use this property in conjunction with the sourceView property to specify the anchor location for the popover.

来自苹果文档:源矩形是指定视图中用于锚定弹出框的矩形。将此属性与 sourceView 属性结合使用来指定弹出框的锚点位置。

In your case, under

在你的情况下,在

_popoverPresentationController.sourceView = self.view;

add:

添加:

_popoverPresentationController.sourceRect = CGRectMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds),0,0)

It will do the trick!

它会做的伎俩!

enter image description here

在此处输入图片说明

回答by Johan Tingbacke

Here's an implementation using Swift 3

这是使用Swift 3的实现

let popover = storyboard?.instantiateViewController(withIdentifier: "popover") as! PopoverVC

    popover.modalPresentationStyle = UIModalPresentationStyle.popover
    popover.popoverPresentationController?.backgroundColor = UIColor.green
    popover.popoverPresentationController?.delegate = self

    popover.popoverPresentationController?.sourceView = self.view
    popover.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)

    popover.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)

    self.present(popover, animated: true)

Based on Istvan's answer

基于 Istvan 的 回答

回答by fethica

Swift 4implementation :

Swift 4实现:

popover.popoverPresentationController?.sourceRect = CGRect(x: view.center.x, y: view.center.y, width: 0, height: 0)
popover.popoverPresentationController?.sourceView = view
popover.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)

回答by instanceof

Another way for Swift 3 (Xcode 8, iOS 9) is this:

Swift 3(Xcode 8,iOS 9)的另一种方法是:

Called from somewhere:

从某处调用:

self.performSegue(withIdentifier: "showPopupSegue", sender: yourButton)

Function that gets called before segue gets fired:

在 segue 被触发之前被调用的函数:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let popoverPresentationController = segue.destination.popoverPresentationController {
        let controller = popoverPresentationController
        controller.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)
        controller.sourceView = self.view
        controller.sourceRect = CGRect(x: UIScreen.main.bounds.width * 0.5 - 200, y: UIScreen.main.bounds.height * 0.5 - 100, width: 400, height: 200)
        segue.destination.preferredContentSize=CGSize(width: 400, height: 200)
    }
}

Remember to set the storyboard segue's Kind attribute to "Present as Popover" and Anchor attribute to any view in your previous view controller.

请记住将 storyboard segue 的 Kind 属性设置为“Present as Popover”,并将 Anchor 属性设置为之前视图控制器中的任何视图。

回答by Kiran K

Swift 4 implementation for center Popover controller

中心 Popover 控制器的 Swift 4 实现

let navigationController = UINavigationController(rootViewController: controller)

 navigationController.modalPresentationStyle = .popover      
 navigationController.modalPresentationStyle = UIModalPresentationStyle.popover
 let popover = navigationController.popoverPresentationController
 controller.preferredContentSize = CGSize(width:500,height:600) //manage according to Device like iPad/iPhone
 popover?.delegate = self
 popover?.sourceView = self.view
 popover?.sourceRect = CGRect(x: view.center.x, y: view.     .y, width: 0, height: 0)
 popover?.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)

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

回答by Hugo Alonso

Basically consist of three steps (iOS 8):

基本上包括三个步骤(iOS 8):

1.- Present the view:

1.- 提出观点:

Let's say, you want to show a custom view to ask for a Review to the user.. here the function loadNibForRate()returns an instance of RateDialogloaded from its nib, but you can use here any way you desire to locate your UIViewController

比方说,你想显示一个自定义视图来向用户请求评论......这里的函数loadNibForRate()返回一个RateDialog从它的笔尖加载的实例,但你可以在这里使用任何你想要定位的方式UIViewController

private static func presentCustomDialog(parent: RateDialogParent) -> Bool {
    /// Loads the rateDialog from its xib, handled this way for further customization if desired
      if let rateDialog = loadNibForRate() {
        rateDialog.modalPresentationStyle = UIModalPresentationStyle.Popover
        rateDialog.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
        let x = parent.view.center

        let sourceRectX : CGFloat
        //Here we check for the orientation of the device, just to know if we are on an iPad
        let maximumDim = max(UIScreen.mainScreen().bounds.height, UIScreen.mainScreen().bounds.width)
        if maximumDim == 1024 { //iPad
            sourceRectX = x.x
        }else {
            sourceRectX = 0
        }

        rateDialog.popoverPresentationController?.sourceView = parent.view
        rateDialog.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.allZeros
        rateDialog.popoverPresentationController?.sourceRect = CGRectMake(sourceRectX, x.y, 0, 0)
        rateDialog.popoverPresentationController?.popoverLayoutMargins = UIEdgeInsetsMake(0, 0, 0, 0)
        rateDialog.popoverPresentationController?.delegate = parent

        rateDialogParent = parent

        callFunctionAsync() {
            parent.presentViewController(rateDialog, animated: true, completion: nil)
        }
        return true
    }
    return false
}

2.- If we rotate our device, then the popover will not know where to reposition itself, unless we have this on the parent RateDialogParent

2.- 如果我们旋转我们的设备,那么 popover 将不知道在哪里重新定位自己,除非我们在父设备上有这个 RateDialogParent

public class RateDialogParent: UIViewController, UIPopoverPresentationControllerDelegate {
/**
This function guarantees that the RateDialog is alwas centered at parent, it locates the RateDialog's view by searching for its tag (-555)
 */
 public func popoverPresentationController(popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverToRect rect: UnsafeMutablePointer<CGRect>, inView view: AutoreleasingUnsafeMutablePointer<UIView?>) {
    if popoverPresentationController.presentedViewController.view.tag == RateDialog.thisViewTag {
        let x = popoverPresentationController.presentingViewController.view.center
        let newRect = CGRectMake(x.x, x.y, 0, 0)
        rect.initialize(newRect)
    }
 }
}

3.- Your RateDialogshould have a tag setted, this is just to avoid relocating unwanted popovers if there is more that one presented from your RateDialogParent

3.- 你RateDialog应该设置一个标签,这只是为了避免重新定位不需要的弹出框,如果有更多的弹出框从你的RateDialogParent

class RateDialog: UIViewController {
 @IBOutlet weak var reviewTitle: UILabel!
 @IBOutlet weak var reviewMessage : UILabel!
 @IBOutlet weak var cancelButtonTitle: UIButton!
 @IBOutlet weak var remindButtonTitle : UIButton!
 @IBOutlet weak var rateButtonTitle : UIButton!

    /// For being able to locate this view
 static let thisViewTag = -555

 override func viewDidLoad() {
    super.viewDidLoad()
    //sets the tag to identify this view
    self.view.tag = RateDialog.thisViewTag
 }
}

回答by Sohil R. Memon

In iOS8, you don't need to use self.view.frameto calculate width and height.

在iOS8中,你不需要使用self.view.frame来计算宽度和高度。

You can the dialog height and width using the following way:

您可以使用以下方式设置对话框的高度和宽度:

override func viewDidLoad() {
     var frameSize: CGPoint = CGPointMake(UIScreen.mainScreen().bounds.size.width*0.5, UIScreen.mainScreen().bounds.size.height*0.5)
     self.preferredContentSize = CGSizeMake(frameSize.x,frameSize.y);
}

Edited:

编辑:

You can also set contentSizeForViewInPopoveras below too:

您也可以设置contentSizeForViewInPopover如下:

self.contentSizeForViewInPopover = CGSizeMake(320.0, 360.0)

Let me know this helps or not?

让我知道这有帮助还是没有?

回答by infiniteLoop

In case if it helps anyone, I have created an extension on UIViewController

如果它对任何人有帮助,我已经在 UIViewController 上创建了一个扩展

extension UIViewController{
    func configureAsPopoverAndPosition(withWidthRatio widthRatio:CGFloat,
                                       heightRatio:CGFloat){
        modalPresentationStyle = .popover
        let screenWidth = UIScreen.main.bounds.width
        let screenHeight = UIScreen.main.bounds.height
        let popover = popoverPresentationController
        popover?.sourceView = self.view

        popover?.permittedArrowDirections = [UIPopoverArrowDirection(rawValue: 0)]
        preferredContentSize = CGSize(width: (screenWidth * widthRatio),
                                      height: (screenHeight * heightRatio))

        popover?.sourceRect = CGRect(x: view.center.x,
                                     y: view.center.y,
                                     width: 0,
                                     height: 0)
    }
}

Usage:

用法:

if UIDevice.current.userInterfaceIdiom == .pad{
                    yourViewController.configureAsPopoverAndPosition(withWidthRatio: 0.7 /*Make view controller width 70 % of screen width*/,
                                                                        heightRatio: 0.7/*Make view controller height 70 % of screen height*/)
                }

This will show the popover at center of the screen.

这将在屏幕中央显示弹出窗口。

回答by imu

Swift 4.1

斯威夫特 4.1

Here is the simple solution:

这是简单的解决方案:

Take a public variable var popover

取一个公共变量 var popover

var popover: UIPopoverPresentationController?

Present YourViewControlleras popover, use the popover?.sourceRectas mentioned below.

目前YourViewController如酥料饼,使用popover?.sourceRect如下所述。

let storyboard: UIStoryboard = UIStoryboard(name: "YOUR_STORYBOARD", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "YOUR_IDENTIFIER") as! YourViewController
let navController = UINavigationController(rootViewController: vc)
navController.modalPresentationStyle = UIModalPresentationStyle.popover
popover = yourController.popoverPresentationController!
popover?.sourceRect = CGRect(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY, width: 0, height: 0)
popover?.sourceView = self.view
popover?.delegate = self
popover?.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)
vc.preferredContentSize = CGSize(width: width, height: height)
self.present(navController, animated: true, completion: nil)

use viewWillTransitionfor view transitions landscape and portrait.

使用viewWillTransition的视图过渡风景和肖像。

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
     super.viewWillTransition(to: size, with: coordinator)
     popover?.sourceRect = CGRect(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY, width: 0, height: 0)
}

this will give you popover center aligned to screen in both landscape and portrait. Much flexible while using split view for iPad.

这将使您的弹出窗口中心与横向和纵向屏幕对齐。使用 iPad 的拆分视图时非常灵活。

回答by AP_

Add the below mentioned line of code to make it centre.

添加下面提到的代码行以使其居中。

popoverController.popoverPresentationController?.sourceView = view

popoverController.popoverPresentationController?.sourceRect = view.bounds