2015-08-01 19 views
27

Mam następujący kod, aby wyświetlić widok na popover (okno dialogowe) bez strzałki, która działa poprawnie. Jedynym problemem jest to, że okno dialogowe jest wyświetlane w lewym górnym rogu (IPad). Chciałbym wyśrodkować widok na ekranie.Jak wyśrodkować wyskakujący ekran w trybie szybkim

Co zmienić lub dodać w poniższym kodzie? :

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

} 

Dodatkowe Informacje

enter image description here

Moim zdaniem, która jest związana z moim viewcontroller ustawić preferowany rozmiar takiego:

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

można po prostu opublikować zrzut ekranu? Czy mogę wiedzieć, że w pełni się pojawia? –

+0

Wielkie dzięki za pomoc. Właśnie dodałem zrzut ekranu i trochę kodu z mojego widoku. Niebieski kolor to tło. Biały to mój popover. Dodatkowy kod pokazuje, że ustawiłem preferowany rozmiar popover. –

+0

Zwykle w takim przypadku powinieneś używać 'popoverLayoutMargins'. Ale spójrz tutaj: http://stackoverflow.com/a/26632329/826716, jest uszkodzony w iOS 8. – bteapot

Odpowiedz

54

Musisz podać źródło rect dla popover.

Z dokumentacji jabłka: źródło rect jest prostokątem w określonym widoku, w którym zakotwiczono popover. Użyj tej właściwości w połączeniu z właściwością sourceView, aby określić położenie zakotwiczenia dla popover.

W twoim przypadku, pod

_popoverPresentationController.sourceView = self.view; 

add:

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

Będzie rade!

enter image description here

+3

Wygląda na to, że po rotacji nie pozostaje w środku. Wszelkie sugestie dotyczące centrowania alertu? – nurider

+0

Opracował rozwiązanie w obj-c, które utrzymuje go w centrum. [Zobacz odpowiedź na stos tutaj] (http://stackoverflow.com/questions/25882133/change-action-sheet-popover-arrow-in-ios8/32750738#32750738). – nurider

+0

Można to wyśrodkować za pomocą scenorysu. IE mój popover segue jest tworzony w storyboardie, mogę ustawić punkt kontrolny do widoku, ale nie mogę dowiedzieć się, jak centrować. – lostintranslation

1

W systemów iOS 8, ty nie trzeba używać self.view.frame do obliczania szerokości i wysokości.

Można wysokość dialogowe i szerokość stosując następujący sposób:

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

edycja:

Można również ustawić contentSizeForViewInPopover jak poniżej zbyt:

self.contentSizeForViewInPopover = CGSizeMake(320.0, 360.0) 

Daj mi znać, że to pomaga albo nie?

+0

Dzięki za pomoc, ale nadal ten sam problem. Właśnie zamieniłem moją preferowanąContentsSize na twoją, ale dialog nadal znajduje się w lewym górnym rogu. –

+0

@mcflysoft zobacz moją zmienioną odpowiedź –

+0

Próbowałem, ale XCode mówi: "" contentSizeforViewinPopover "jest niedostępna: Użyj UIViewController.preferredContentSize zamiast". Próbowałem również z self.view.contentSizeForViewInPopover = CGSizeMake (320.0, 360.0), ale metoda "contentSizeforViewinPopover" jest niedostępna. –

1

Zasadniczo składa się z trzech etapów (iOS 8):

1.- obecny pogląd:

powiedzmy chcesz pokazać widoku niestandardowego poprosić o opinię dla użytkownika .. tutaj funkcja loadNibForRate() zwraca instancję RateDialog załadowaną z jego końcówki, ale można tu użyć w dowolny sposób, aby zlokalizować 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.- Jeśli będziemy obracać naszego urządzenia, a następnie popover nie będą wiedzieć, gdzie, aby zmienić siebie, chyba że mamy to na rodzica 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.- Twój RateDialog powinien tag setted jest to po prostu, aby uniknąć niechcianych popovers przeprowadzki, jeśli istnieje więcej niż jeden przedstawiony z 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 
} 
} 
23

Oto implementacja przy użyciu 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) 

podstawie Istvana answer

3

Innym sposobem Swift 3 (Xcode 8, iOS 9) jest taka:

Called skądś :

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

Funkcja, która jest wywoływana przed segue zostaje zwolniony:

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

Pamiętaj, aby ustawić serii ujęć Segue rodzaj atrybutu „Present” i jako popover Anchor atrybutu do dowolnego widoku w poprzednim kontrolera widoku.

2

Swift 4 realizacja:

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) 
Powiązane problemy