İOS 8'de popover nasıl düzgün bir şekilde gösterilir


118

Swift iOS 8 uygulamama bir UIPopoverView eklemeye çalışıyorum, ancak açılır pencere doğru şekilde gösterilmediği için PopoverContentSize özelliğine erişemiyorum. benim kodum:

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

çıktı:

görüntü açıklamasını buraya girin

UIPopoverPresentationController aracılığıyla aynı şeyi yaptığım zaman, yine de yapamıyorum. bu benim kodum:

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)

}

Aynı çıktıyı alıyorum.

Açılır bilgi penceremin boyutunu nasıl özelleştirebilirim? Herhangi bir yardım çok takdir edilecektir!


Geliştirici sitesinde "A Look Inside Presentation Controllers" adlı bir WWDC videosu var. UIPopoverPresentationController
Wextux

Sorumu UIpopoverpresentationctontroller ile ilgili apple videosuna göre düzenledim, ancak hiçbir şey değişmedi! bu konuda değiştirmem gereken bir şey görüyor musun? Yine de girdi için teşekkürler!
Joris416

Yanıtlar:


148

Tamam, bir ev arkadaşı ona bir göz attı ve anladı:

 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)

}

Yol bu.

Artık açılır pencerenin kendisiyle konuşmuyorsunuz, özelliği çağırarak içerik boyutunu ayarlamak için içindeki görünüm denetleyicisiyle konuşuyorsunuz preferredContentSize


15
Muhtemelen bariz olanı belirtiyor, ama bu sadece hızlı ile ilgili değil. Bunu obj-c uygulamamda da yapmak zorunda kaldım :)
Kevin R

4
Kodla ilgili başka bir yorum - "var" yerine "izin ver" kullanabilirsiniz. Apple, değeri yeniden atamanıza gerek olmayan durumlarda bunu önerir.
EPage_Ed

3
Bu iPhone için GM'de dinleniyor. Simülatör dikey moddayken sunum yapmaya çalışırsanız her zaman tam ekran olur. Manzaraya döndürürseniz, bir açılır pencere olur. Tekrar dikey konuma döndürürseniz, bir açılır pencere olarak kalır.
jjxtra

1
Çözüm, presentViewController'ı çağırmadan ÖNCE açılır pencereyi ayarlamaktır. Bu, açık bir şekilde size presentViewController'ı çağırdıktan SONRA açılır pencereyi ayarlamanızı söylediği Apple örneğinin tam tersidir.
jjxtra

1
@ PsychoDad, bahsettiğiniz bu çözüme bağlantı sağlayabilir misiniz? Hala "simülatör dikey moddayken, her zaman tam ekran" şeklinde takılıyorum. Teşekkürler
Nishant

53

Aslında bundan çok daha basit. Film şeridinde, açılır pencere olarak kullanmak istediğiniz görüntü denetleyicisini yapmalı ve bunun için her zamanki gibi bir görüntü denetleyici sınıfı yapmalısınız. Açılır pencereyi açmak istediğiniz nesneden, bu durumda UIBarButton"Config" adlı nesneden aşağıda gösterildiği gibi bir segment oluşturun .

görüntü açıklamasını buraya girin

"Ana görünüm denetleyicisinde" UIPopoverPresentationControllerDelegateve temsilci yöntemini uygulayın:

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

prepareForSequeYöntemi şu şekilde geçersiz kılın :

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

Ve bitirdiniz. Ve artık açılır pencere görünümünü başka herhangi bir görünüm gibi ele alabilirsiniz, yani. alanlar ekleyin ve ne değil! Ve içerik denetleyicisine şu popoverPresentationController.presentedViewControlleryöntemi kullanarak sahip olursunuz:UIPopoverPresentationController .

Ayrıca bir iPhone'da üzerine yazmanız gerekir

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

        return UIModalPresentationStyle.none
    } 

28

Tüm bunların nasıl çalıştırılacağına dair eksiksiz bir örnek buldum, böylece cihaz / yön https://github.com/frogcjn/AdaptivePopover_iOS8_Swift ne olursa olsun her zaman bir açılır pencere görüntüleyebilirsiniz .

Anahtar, UIAdaptivePresentationControllerDelegate'i uygulamaktır

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

Ardından yukarıdaki örneği genişletin (Imagine Digital'den):

nav.popoverPresentationController!.delegate = implOfUIAPCDelegate

UIPopoverPresentationControllerDelegate
onmyway133

3
Doğru, UIPopoverPresentationControllerDelegate UIAdaptivePresentationControllerDelegate'i genişletir. Bu nedenle, tanım gereği her ikisi de 'adaptivePresentationStyleForPresentationController' yöntemini içerir. Temel arayüzü, yöntemin Apple'ın API belgelerinde belgelendiği yer olarak sağladım.
David Hunt

1
Bunun belgelenmemiş bir davranış olduğunu unutmayın. Doküman, bu temsilci yönteminin "ya UIModalPresentationFullScreenda UIModalPresentationOverFullScreen" döndürmesi gerektiğini söylüyor . Ayrıca, "Bu yöntemi uygulamak veya dışında herhangi bir stil dönmezsem UIModalPresentationFullScreenya UIModalPresentationOverFullScreen, sunum kontrolörü sunum biçimini düzenleyen UIModalPresentationFullScreentarzı."
Tom

1
Mevcut belgeler, iOS 8.3'ten itibaren - adaptivePresentationStyleForPresentationController: traitCollection: kullanmanız gerektiğini ve döndürülen stilin "UIModalPresentationFullScreen, UIModalPresentationOverFullScreen, UIModalPresentationFormSheet veya UIModalPresentationNone" olması gerektiğini önermektedir.
Dale

25

Swift 2.0

Ben çalıştım. Bir göz atın. StoryBoard'da bir ViewController yaptı. PopOverViewController sınıfıyla ilişkilendirilmiştir.

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'a bakın:

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

Not: func showPopover (temel: UIView) yöntemi ViewDidLoad'dan önce yerleştirilmelidir. Umarım yardımcı olur !


merhaba @Alvin, harita açıklamasından bir görünüm açacağım. Ben de seninle aynısını yaptım. aradaki fark, view yerine tableviewcontroller'ı dolduracağım. Artık sorun temsilci yöntemine vurmak değil. "PopoverPresentationControllerDidDismissPopover". denetleyiciyi kapattığımda. Yardım edebilir misin ? (soru
gönderiyle

1
Neden showPopover(base: UIView)önce bir yöntem yerleştirilmeli viewDidLoad()?
Eimantas

15

İOS9'da UIPopoverController amortismana tabi tutulmuştur. Dolayısıyla, iOS9.x üzerindeki Objective-C sürümü için aşağıdaki kodu kullanabilirsiniz,

- (IBAction)onclickPopover:(id)sender {
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
UIViewController *viewController = [sb instantiateViewControllerWithIdentifier:@"popover"];

viewController.modalPresentationStyle = UIModalPresentationPopover;
viewController.popoverPresentationController.sourceView = self.popOverBtn;
viewController.popoverPresentationController.sourceRect = self.popOverBtn.bounds;
viewController.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:viewController animated:YES completion:nil]; }

Soru özellikle Swift'i istiyor, Objective-C'yi değil.
Eric Aya

8

Burada "Joris416" Swift Kodunu Objective-c'ye Dönüştürüyorum,

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

EKLEMEYİ UNUTMAYIN
UIPopoverPresentationControllerDelegate, UIAdaptivePresentationControllerDelegate


Soru özellikle Swift'i istiyor, Objective-C'yi değil.
Eric Aya

4

Bu en iyi iOS8 Günlük blogunda açıklanmaktadır

Kısacası, UIViewController modalPresentationStyle öğesini .Popover olarak ayarladıktan sonra, denetleyicinin popoverPresentationController özelliği aracılığıyla bir UIPopoverPresentationClass (yeni bir iOS8 sınıfı) elde edebilirsiniz.


3

Yukarıda Imagine Digitals hızlı cevabının Objective-C versiyonunu yaptım. Ön test altında işe yarıyor gibi görünen hiçbir şeyi kaçırdığımı sanmıyorum, bir şey görürseniz bana bildirin, ben de güncelleyeyim

-(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];
}

Sanırım dışarı popover.sourceView = self.view;
çıktın

Soru özellikle Swift'i istiyor, Objective-C'yi değil.
Eric Aya

4
Bunun farkındayım, ancak hedef-C'yi arıyor olsanız bile google sizi buraya getiriyor. Buraya böyle geldim.
narco

3

xcode 9.1 / swift 4 için iki sentim.

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
}

ve deney yapın:

func adaptivePresentationStyle ...

    return .popover

veya: return .pageSheet .... ve benzeri ..


2

Viewcontroller'ınızda UIAdaptivePresentationControllerDelegate'i uygulayın. Sonra Ekle :

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

1

Aşağıda, popover'ların nasıl yapılandırılacağı ve sunulacağı konusunda oldukça kapsamlı bir kılavuz bulunmaktadır. https://www.appcoda.com/presentation-controllers-tutorial/

Özetle, uygun bir uygulama ( Swift 4.2 için orijinal makale sözdiziminden bazı güncellemelerle ), daha sonra başka bir yerden çağrılacak, aşağıdaki gibi bir şey olacaktır:

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

Bunların çoğu @mmc'den gelen yanıtta zaten ele alınmıştı, ancak makale kullanılan bu kod öğelerinin bazılarını açıklamaya yardımcı oluyor ve ayrıca nasıl genişletilebileceğini gösteriyor.

Ayrıca, iPhone ve iPad için sunum stilini işlemek ve açılır pencerenin tam ekran gösterilmesi durumunda kapatılmasına izin vermek için yetkilendirmeyi kullanma hakkında birçok ek ayrıntı sağlar. Yine Swift 4.2 için güncellendi :

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

Bu yardımcı olur umarım.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.