iOS 8でポップオーバーを適切に表示する方法


118

UIPopoverViewをSwift iOS 8アプリに追加しようとしていますが、PopoverContentSizeプロパティにアクセスできません。ポップオーバーが正しい形で表示されないためです。私のコード:

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

出力:

ここに画像の説明を入力してください

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)

}

まったく同じ出力が得られます。

ポップオーバーのサイズをカスタマイズするにはどうすればよいですか?どんな助けでも大歓迎です!


開発者サイトには、「A Look Inside Presentation Controllers」というWWDCビデオがあります。UIPopoverPresentationControllerの使用方法について説明しています
Wextux '

UIpopoverpresentationctontrollerに関するアップルビデオに従って質問を編集しましたが、何も変わりませんでした。これについて私が変更すべきことは何かありますか?入力ありがとうございます!
Joris416 2014

回答:


148

さて、ハウスメイトはそれを見て、それを理解しました:

 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)

}

それが方法です。

プロパティを呼び出して、ポップオーバー自体とはもう対話せず、その中のビューコントローラーと対話してコンテンツサイズを設定します。 preferredContentSize


15
おそらく明白なことを述べているでしょうが、これは迅速なことだけではありません。私もobj-cアプリでこれを行わなければなりませんでした:)
Kevin R

4
コードに関する別のコメント-「var」の代わりに「let」を使用できます。値を再割り当てする必要がない場合は、Appleが推奨します。
EPage_Ed 2014

3
これはiPhoneのGMにバグがあります。シミュレーターが縦向きのときにプレゼンテーションしようとすると、常にフルスクリーンになります。横に回転するとポップオーバーになります。再び縦に戻すと、ポップオーバーのままになります。
jjxtra 2014

1
解決策は、presentViewControllerを呼び出す前にポップオーバーを設定することです。これは、presentViewControllerを呼び出した後にポップオーバーを設定するように明示的に指示するAppleの例とは正反対です。
jjxtra 14

1
@PsychoDadは、このソリューションへのリンクを記載してください。私はまだ「シミュレーターがポートレートにある間、それは常にフルスクリーンです」で立ち往生しています。ありがとう
Nishant 2014

53

実際にはそれよりもはるかに単純です。ストーリーボードで、ポップオーバーとして使用するビューコントローラーを作成し、通常のようにビューコントローラークラスを作成する必要があります。以下のように、ポップオーバーを開きたいオブジェクト(この場合はUIBarButton「Config」という名前)からセグエを作成します。

ここに画像の説明を入力してください

「マザービューコントローラ」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
    } 

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

私はUIPopoverPresentationControllerDelegateを使用しています
onmyway133

3
正しい、UIPopoverPresentationControllerDelegateはUIAdaptivePresentationControllerDelegateを拡張します。したがって、どちらの定義にも、「adaptivePresentationStyleForPresentationController」というメソッドが含まれています。メソッドがAppleのAPIドキュメントに記載されているベースインターフェイスを提供しました。
David Hunt、

1
これは文書化されていない動作であることに注意してください。ドキュメントは、このデリゲートメソッドは「どちらかUIModalPresentationFullScreenまたはUIModalPresentationOverFullScreen」を返す必要があると述べています。さらに、「このメソッドを実装しないUIModalPresentationFullScreenUIModalPresentationOverFullScreen、または以外のスタイルを返す場合、プレゼンテーションコントローラーはプレゼンテーションスタイルをスタイルに調整しUIModalPresentationFullScreenます。」
トム

1
現在のドキュメントでは、iOS 8.3以降では-adaptivePresentationStyleForPresentationController:traitCollection:を使用する必要があり、返されるスタイルは「UIModalPresentationFullScreen、UIModalPresentationOverFullScreen、UIModalPresentationFormSheet、またはUIModalPresentationNone」である必要があります。
Dale

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の前に配置する必要があります。それが役に立てば幸い !


こんにちは、@ Alvinです。マップアノテーションからビューをポップアップします。だから私はあなたと同じようにやった。違いは、ビューではなくtableviewcontrollerにデータが入力されることです。現在、問題はデリゲートメソッド。 "popoverPresentationControllerDidDismissPopover"にヒットしていません。コントローラを却下したとき。手伝ってくれますか ?(質問は投稿に関連していません)
Subin K Kuriakose

1
なぜshowPopover(base: UIView)メソッドを前に置く必要があるのviewDidLoad()ですか?
Eimantas 2017

15

iOS9では、UIPopoverControllerは廃止されました。したがって、iOS9.xよりも上のObjective-Cバージョンには、以下のコードを使用できます。

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

問題は具体的にはObjective-CではなくSwiftを求めます。
Eric Aya

8

ここでは、「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


問題は具体的にはObjective-CではなくSwiftを求めます。
Eric Aya

4

これはiOS8の日々のブログで最もよく説明されています

つまり、UIViewControllerのmodalPresentationStyleを.Popoverに設定すると、コントローラーのpopoverPresentationControllerプロパティを介してUIPopoverPresentationClass(新しいiOS8クラス)を取得できます。


3

上記の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];
}

私はあなたが取り残したと思います popover.sourceView = self.view;
ghr

問題は具体的にはObjective-CではなくSwiftを求めます。
Eric Aya

4
私はそれを理解していますが、あなたがobjective-Cを探しているとしても、グーグルはあなたをここに連れてきます。それが私がここで終わった方法です。
ナルコ

3

私の2セントで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

または:.pageSheet ....などを返します。


2

ViewAdapterにUIAdaptivePresentationControllerDelegateを実装します。それから加えて :

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

1

以下に、ポップオーバーの構成方法と表示方法に関するかなり包括的なガイドがあります。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)
}

お役に立てれば。


0

勉強したい方に!

私は、ポップオーバービューを研究し、あらゆる目的で使用したい人のために、オープンソースプロジェクトを作成しました。ここでプロジェクトを見つけることができます。https://github.com/tryWabbit/KTListPopup

KTListNewResize

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.