Cách hiển thị cửa sổ bật lên đúng cách trong iOS 8


118

Tôi đang cố gắng thêm UIPopoverView vào ứng dụng Swift iOS 8 của mình, nhưng tôi không thể truy cập thuộc tính PopoverContentSize, vì cửa sổ bật lên không hiển thị theo đúng hình dạng. mã của tôi:

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

đầu ra:

nhập mô tả hình ảnh ở đây

Khi tôi đang làm điều tương tự thông qua UIPopoverPresentationController, tôi vẫn chưa hoàn thành. đây là mã của tôi:

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)

}

Tôi nhận được cùng một đầu ra.

Làm cách nào để tùy chỉnh kích thước cửa sổ bật lên của tôi? Bất cứ sự giúp đỡ nào cũng được đánh giá cao!


Có một đoạn video WWDC trên trang web nhà phát triển gọi là "A Look Bên Presentation Bộ xử lý" Nó giải thích làm thế nào để sử dụng UIPopoverPresentationController
Wextux

Tôi đã chỉnh sửa câu hỏi của mình theo video apple về UIpopoverpresentationctontroller, nhưng không có gì thay đổi! Bạn có thể biết bất cứ điều gì mà tôi nên thay đổi về điều này? Cảm ơn vì đầu vào mặc dù!
Joris416

Câu trả lời:


148

Được rồi, một người bạn cùng nhà đã xem qua và tìm ra:

 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)

}

Đó là cách.

Bạn không nói chuyện với chính cửa sổ bật lên nữa, bạn nói chuyện với bộ điều khiển chế độ xem bên trong nó để đặt kích thước nội dung, bằng cách gọi thuộc tính preferredContentSize


15
Có thể nói rõ ràng, nhưng điều này không chỉ liên quan nhanh chóng. Tôi cũng phải làm điều này trong ứng dụng obj-c của mình :)
Kevin R

4
Một nhận xét khác về mã - bạn có thể sử dụng "let" thay vì "var". Apple đề xuất nó cho những trường hợp bạn không cần chỉ định lại giá trị.
EPage_Ed

3
Điều này được ghi âm trong GM dành cho iPhone. Nếu bạn cố gắng trình bày trong khi trình mô phỏng ở chế độ dọc, nó luôn ở chế độ toàn màn hình. Nếu bạn xoay ngang, nó sẽ trở thành một cửa sổ bật lên. Nếu bạn xoay trở lại chế độ dọc một lần nữa, nó vẫn là một cửa sổ bật lên.
jjxtra

1
Giải pháp là thiết lập cửa sổ bật lên TRƯỚC KHI gọi presentViewController. Điều này hoàn toàn ngược lại với ví dụ của Apple nơi họ yêu cầu bạn thiết lập cửa sổ bật lên SAU KHI gọi presentViewController.
jjxtra

1
@PsychoDad bạn có thể vui lòng cung cấp liên kết đến giải pháp này mà bạn đã đề cập. Tôi vẫn bị mắc kẹt ở "trong khi trình mô phỏng ở chế độ dọc, nó luôn ở chế độ toàn màn hình". Cảm ơn
Nishant

53

Thực ra nó đơn giản hơn thế rất nhiều. Trong bảng phân cảnh, bạn nên đặt bộ điều khiển chế độ xem mà bạn muốn sử dụng làm cửa sổ bật lên và tạo một lớp bộ điều khiển chế độ xem cho nó như bình thường. Tạo một phân vùng như hình dưới đây từ đối tượng bạn muốn mở cửa sổ bật lên, trong trường hợp này UIBarButtonlà "Cấu hình".

nhập mô tả hình ảnh ở đây

Trong "bộ điều khiển chế độ xem mẹ", hãy triển khai UIPopoverPresentationControllerDelegatevà phương thức ủy quyền:

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

Ghi đè prepareForSequephương thức như thế này:

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

Và bạn đã hoàn thành. Và bây giờ bạn có thể coi dạng xem popover như bất kỳ dạng xem nào khác, tức là. thêm trường và những gì không! Và bạn nắm được trình điều khiển nội dung bằng cách sử dụng popoverPresentationController.presentedViewControllerphương thức trong UIPopoverPresentationController.

Ngoài ra trên iPhone, bạn sẽ phải ghi đè

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

        return UIModalPresentationStyle.none
    } 

28

Tôi đã tìm thấy một ví dụ đầy đủ về cách làm cho tất cả điều này hoạt động để bạn luôn có thể hiển thị cửa sổ bật lên bất kể thiết bị / hướng nào https://github.com/frogcjn/AdaptivePopover_iOS8_Swift .

Chìa khóa là triển khai UIAdaptivePresentationControllerDelegate

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

Sau đó, mở rộng ví dụ trên (từ Imagine Digital):

nav.popoverPresentationController!.delegate = implOfUIAPCDelegate

Tôi sử dụng UIPopoverPresentationControllerDelegate
onmyway133

3
Đúng, UIPopoverPresentationControllerDelegate mở rộng UIAdaptivePresentationControllerDelegate. Vì vậy, theo định nghĩa, cả hai đều chứa phương thức 'adaptivePresentationStyleForPresentationController'. Tôi đã cung cấp giao diện cơ sở vì đó là nơi phương pháp được ghi lại trong tài liệu API của Apple.
David Hunt

1
Lưu ý đây là hành vi không có giấy tờ. Tài liệu cho biết phương thức ủy quyền này phải trả về "hoặc UIModalPresentationFullScreenhoặc UIModalPresentationOverFullScreen". Hơn nữa, "Nếu bạn không triển khai phương pháp này hoặc trả về bất kỳ kiểu nào khác với UIModalPresentationFullScreenhoặc UIModalPresentationOverFullScreen, bộ điều khiển bản trình bày sẽ điều chỉnh kiểu trình bày theo UIModalPresentationFullScreenkiểu."
Tom,

1
Tài liệu hiện tại khuyên rằng từ iOS 8.3 trở đi bạn nên sử dụng - adaptivePresentationStyleForPresentationController: traitCollection: và kiểu trả về đó phải là "UIModalPresentationFullScreen, UIModalPresentationOverFullScreen, UIModalPresentationFormSheet hoặc UIModalPresentationNone."
Dale

25

Swift 2.0

Vâng, tôi đã làm việc ra. Hãy xem. Tạo một ViewController trong StoryBoard. Liên kết với lớp 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)
    }
}      

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

Lưu ý: Phương thức func showPopover (base: UIView) nên được đặt trước ViewDidLoad. Hy vọng nó giúp !


xin chào @Alvin, tôi sẽ bật lên một chế độ xem từ chú thích bản đồ. vì vậy tôi đã làm giống như bạn đã làm. sự khác biệt là tôi sẽ điền bảng điều khiển thay vì chế độ xem. Bây giờ vấn đề không phải là đánh vào phương thức đại biểu. "PopoverPresentationControllerDidDismissPopover". khi tôi loại bỏ bộ điều khiển. bạn có thể giúp ? (câu hỏi không liên quan đến các bưu điện)
Subin K Kuriakose

1
Tại sao một showPopover(base: UIView)phương thức nên được đặt trước viewDidLoad()?
Eimantas

15

Trong iOS9 UIPopoverController bị giảm giá trị. Vì vậy, có thể sử dụng mã dưới đây cho phiên bản Objective-C trên iOS9.x,

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

Câu hỏi đặc biệt dành cho Swift, không phải cho Objective-C.
Eric Aya

8

Ở đây tôi chuyển đổi mã Swift "Joris416" thành 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;
}

Nhớ THÊM
UIPopoverPresentationControllerDelegate, UIAdaptivePresentationControllerDelegate


Câu hỏi đặc biệt dành cho Swift, không phải cho Objective-C.
Eric Aya

4

Điều này được giải thích tốt nhất trên blog Ngày qua ngày của iOS8

Nói tóm lại, sau khi bạn đặt modalPresentationStyle của UIViewController thành .Popover, bạn có thể nắm giữ UIPopoverPresentationClass (một lớp iOS8 mới) thông qua thuộc tính popoverPresentationController của bộ điều khiển.


3

Tôi đã trả lời nhanh phiên bản Objective-C của Imagine Digitals ở trên. Tôi không nghĩ rằng tôi đã bỏ lỡ bất cứ điều gì vì nó dường như đang hoạt động trong quá trình thử nghiệm sơ bộ, nếu bạn phát hiện ra điều gì đó, hãy cho tôi biết và tôi sẽ cập nhật nó

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

Tôi nghĩ bạn đã bỏ popover.sourceView = self.view;
dở

Câu hỏi đặc biệt dành cho Swift, không phải cho Objective-C.
Eric Aya

4
Tôi nhận ra điều đó, nhưng google sẽ đưa bạn đến đây ngay cả khi bạn đang tìm kiếm mục tiêu-C. Đó là cách tôi kết thúc ở đây.
tuý

3

hai xu của tôi cho 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
}

và thử nghiệm trong:

func adaptivePresentationStyle ...

    return .popover

hoặc: return .pageSheet .... và như vậy ..


2

Triển khai UIAdaptivePresentationControllerDelegate trong Viewcontroller của bạn. Sau đó thêm:

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

1

Phần sau có một hướng dẫn khá toàn diện về cách định cấu hình và trình bày các cửa sổ bật lên. https://www.appcoda.com/presentation-controllers-tutorial/

Tóm lại, một triển khai khả thi (với một số cập nhật từ cú pháp bài viết gốc cho Swift 4.2 ), sau đó được gọi từ nơi khác, sẽ giống như sau:

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

Rất nhiều điều này đã được đề cập trong câu trả lời từ @mmc, nhưng bài viết giúp giải thích một số phần tử mã được sử dụng và cũng chỉ ra cách nó có thể được mở rộng.

Nó cũng cung cấp nhiều chi tiết bổ sung về cách sử dụng ủy quyền để xử lý kiểu trình bày cho iPhone so với iPad và cho phép loại bỏ cửa sổ bật lên nếu nó được hiển thị toàn màn hình. Một lần nữa, đã cập nhật cho 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)
}

Hi vọng điêu nay co ich.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.