Подтвердить что ты не робот

Как центрировать popoverview в быстром

У меня есть следующий код, чтобы показать popoverview (диалог) без стрелки, которая работает нормально. Единственная проблема заключается в том, что диалог отображается в верхнем левом углу (IPad). Я хотел бы центрировать вид на экране.

Что изменить или добавить в мой следующий код? :

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)
    }

}

Дополнительная информация

enter image description here

На мой взгляд, который связан с моим viewcontroller, я установил предпочтительный размер следующим образом:

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);
}
4b9b3361

Ответ 1

Вам нужно указать источник для popover.

Из документации на ящик: исходный прямоугольник - это прямоугольник в указанном представлении, в котором можно привязать popover. Используйте это свойство вместе с свойством sourceView, чтобы указать местоположение привязки для popover.

В вашем случае под

_popoverPresentationController.sourceView = self.view;

добавить:

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

Это будет трюк!

введите описание изображения здесь

Ответ 2

Здесь реализация с использованием 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)

На основе Иштвана ответ

Ответ 3

Внедрение 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)

Ответ 4

Другим способом для Swift 3 (Xcode 8, iOS 9) является следующее:

Вызывается откуда-то:

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

Функция, вызываемая до начала 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)
    }
}

Не забудьте установить для атрибута segue Kindgate атрибут "Present as Popover" и Anchor для любого представления в вашем предыдущем контроллере представления.

Ответ 5

В основном состоит из трех этапов (iOS 8):

1.- Представьте представление:

Скажем, вы хотите показать пользовательское представление, чтобы запросить отзыв пользователю. здесь функция loadNibForRate() возвращает экземпляр RateDialog, загруженный из его nib, но вы можете использовать его любым способом чтобы найти ваш 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. Если мы повернуть наше устройство, то popover не будет знать, где переместить себя, если у нас нет этого на родительском RateDialogParent

public class RateDialogParent: UIViewController, UIPopoverPresentationControllerDelegate {
/**
This function guarantees that the RateDialog is alwas centered at parent, it locates the RateDialog 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.- Ваш RateDialog должен иметь установленный тэг, это просто, чтобы избежать перемещения нежелательных popovers, если есть больше того, что представлено от вашего 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
 }
}

Ответ 6

Реализация Swift 4 для центрального контроллера Popover

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)

Ответ 7

В iOS8 вам не нужно использовать self.view.frame для вычисления ширины и высоты.

Вы можете изменить высоту и ширину диалогового окна, используя следующий способ:

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);
}

Отредактировано:

Вы также можете установить contentSizeForViewInPopover как показано ниже:

self.contentSizeForViewInPopover = CGSizeMake(320.0, 360.0)

Позвольте мне знать, что это помогает или нет?

Ответ 8

На случай, если это кому-нибудь поможет, я создал расширение на 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)
    }
}

Использование:

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*/)
                }

Это покажет поповер в центре экрана.

Ответ 9

Swift 4.1

Вот простое решение:

Возьмите публичную переменную var popover

var popover: UIPopoverPresentationController?

Представьте YourViewController как popover, используйте 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)

используйте 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)
}

это даст вам центр поповера, выровненный по экрану как в альбомной, так и в портретной ориентации. Много гибкости при использовании разделения просмотра для iPad.

Ответ 10

Добавьте нижеупомянутую строку кода, чтобы сделать его центром.

popoverController.popoverPresentationController?.sourceView = view

popoverController.popoverPresentationController?.sourceRect = view.bounds