带有embedded式导航控制器的popup窗口不考虑back nav上的大小

我有一个UIPopoverController承载一个UINavigationController,其中包含一个小的层次结构的视图控制器。

我跟着文档和每个视图控制器,我设置视图的popup窗口大小像这样:

[self setContentSizeForViewInPopover:CGSizeMake(320, 500)]; 

(每个控制器的大小不同)

当我在层次结构中向前导航时,这会按预期方式工作 – popup窗口自动animation大小更改以对应于推送的控制器。

但是,当我通过导航栏的“后退”button导航“返回”视图堆栈时,popup窗口不会更改大小 – 它将保持与最深的视图一样大。 这似乎打破了我; 我希望popup窗口能够尊重在popup视图堆栈时设置的大小。

我错过了什么吗?

谢谢。

好吧,我正在同样的问题挣扎。 上述的解决scheme都不是很好的为我工作,这就是为什么我决定做一个调查,并找出如何工作。 这就是我发现的: – 当你在你的视图控制器中设置contentSizeForViewInPopover ,它不会被popover本身改变,即使导航到不同的控制器时popover的大小可能会改变。 – 当浏览到不同的控制器时,popup窗口的大小会改变,而popup窗口的大小不会恢复 – 改变viewWillAppearpopup窗口的大小给出非常奇怪的animation(当我们说popup窗口中的popController时)我不会推荐它 – 对我来说,设置控制器内的硬编码大小根本无法工作 – 我的控制器有时会有时很大 – 有时控制器会显示它们的大小

所有这些痛苦的解决scheme如下:您必须在viewDidAppear中重置currentSetSizeForPopover的大小。 但是你必须小心,当你将设置的字段currentSetSizeForPopover设置相同的大小,然后popup不会改变大小。 为此,您可以首先设置假的尺寸(与以前设置的尺寸不同),然后设置合适的尺寸。 即使您的控制器嵌套在导航控制器中,此解决scheme也可以工作,并且当您将在控制器之间导航时,popup窗口将相应地更改其大小。

你可以在UIViewController上用下面的帮助器方法轻松地创build类别,这个方法可以通过设置尺寸来实现:

 - (void) forcePopoverSize { CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover; CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f, currentSetSizeForPopover.height - 1.0f); self.contentSizeForViewInPopover = fakeMomentarySize; self.contentSizeForViewInPopover = currentSetSizeForPopover; } 

然后只需在所需的控制器的-viewDidAppear中调用它。

以下是我如何解决它的iOS 7和8:

在iOS 8中,iOS默默地将您想要的视图封装在presentsViewController视图控制器的renderedViewController中。 有一个2014年的WWDCvideo,解释了他们碰到的popovercontroller的新function。

无论如何,对于导航控制器堆栈中呈现的视图控制器,都需要自己的大小,这些视图控制器需要(在iOS 8下)调用此代码dynamic设置preferredContentSize:

 self.presentingViewController.presentedViewController.preferredContentSize = CGSizeMake(320, heightOfTable); 

将heightOfTablereplace为您的计算表或视图高度。

为了避免大量的重复代码,并创build一个通用的iOS 7和iOS 8解决scheme,我创build了一个UITableViewController的类别来执行这个工作时,我的tableviews中调用viewDidAppear:

 - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self setPopOverViewContentSize]; } 

Category.h:

 #import <UIKit/UIKit.h> @interface UITableViewController (PreferredContentSize) - (void) setPopOverViewContentSize; @end 

Category.m:

 #import "Category.h" @implementation UITableViewController (PreferredContentSize) - (void) setPopOverViewContentSize { [self.tableView layoutIfNeeded]; int heightOfTable = [self.tableView contentSize].height; if (heightOfTable > 600) heightOfTable = 600; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) self.preferredContentSize=CGSizeMake(320, heightOfTable); else self.presentingViewController.presentedViewController.preferredContentSize = CGSizeMake(320, heightOfTable); } } @end 

这是对krasnyk答案的改进。
您的解决scheme非常棒,但不是平滑的animation。
有一点改进给出了很好的animation:

删除- (void) forcePopoverSize方法的最后一行:

 - (void) forcePopoverSize { CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover; CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f, currentSetSizeForPopover.height - 1.0f); self.contentSizeForViewInPopover = fakeMomentarySize; } 

将[self forcePopoverSize]放入- (void)viewWillAppear:(BOOL)animated方法:

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self forcePopoverSize]; } 

最后,在- (void)viewDidAppear:(BOOL)animated设置所需的大小- (void)viewDidAppear:(BOOL)animated方法:

 - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover; self.contentSizeForViewInPopover = currentSetSizeForPopover; } 

您需要在viewWillAppear再次设置内容大小。 通过调用设置popovercontroller大小的delagate方法。 我也有同样的问题。 但是当我添加这个问题解决了。

还有一件事:如果您使用的testing版本小于5,那么popup窗口更难以pipe理。 从testing版本5看来,它们似乎更友好。最终版本已经不错了。 ;)

希望这可以帮助。

在导航控制器中使用的所有视图控制器的-(void)viewDidLoad中,添加:

 [self setContentSizeForViewInPopover:CGSizeMake(320, 500)]; 

我重置viewWillDisappear中的大小:(BOOL)视图控制器的animation方法,从以下位置导航回来:

 -(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; CGSize contentSize = [self contentSizeForViewInPopover]; contentSize.height = 0.0; self.contentSizeForViewInPopover = contentSize; } 

然后,当正在导航的视图出现时,我适当地重新设置大小:

 -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; CGSize contentSize; contentSize.width = self.contentSizeForViewInPopover.width; contentSize.height = [[self.fetchedResultsController fetchedObjects] count] * self.tableView.rowHeight; self.contentSizeForViewInPopover = contentSize; } 

对于iOS 8,以下工作:

 - (void) forcePopoverSize { CGSize currentSetSizeForPopover = self.preferredContentSize; CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f, currentSetSizeForPopover.height - 1.0f); self.preferredContentSize = fakeMomentarySize; self.navigationController.preferredContentSize = fakeMomentarySize; self.preferredContentSize = currentSetSizeForPopover; self.navigationController.preferredContentSize = currentSetSizeForPopover; } 

顺便说一句,我认为,这应该与以前的iOS版本兼容…

 Well i worked out. Have a look. Made a ViewController in StoryBoard. Associated with PopOverViewController class. 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) } } See ViewController: // // ViewController.swift // iOS8-PopOver // // Created by Alvin George on 13.08.15. // Copyright (c) 2015 Fingent Technologies. All rights reserved. // 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 } } Note: The func showPopover(base: UIView) method should be placed before ViewDidLoad. Hope it helps ! 

对我来说,这个解决scheme的工 这是从我的视图控制器扩展UITableViewController,是UINavigationController的根控制器的方法。

 -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; self.contentSizeForViewInPopover = self.tableView.bounds.size; } 

不要忘了设置视图控制器的内容大小,你会推入导航堆栈

 - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{ dc = [[DetailsController alloc] initWithBookmark:[[bookmarksArray objectAtIndex:indexPath.row] retain] bookmarkIsNew:NO]; dc.detailsDelegate = self; dc.contentSizeForViewInPopover = self.contentSizeForViewInPopover; [self.navigationController pushViewController:dc animated:YES]; } 

如果你可以想象这个阿甘,我觉得这样稍微好一些:

 - (void)forcePopoverSize {
     CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover;
     self.contentSizeForViewInPopover = CGSizeMake(0,0);
     self.contentSizeForViewInPopover = currentSetSizeForPopover;
 }

接受的答案是不能正常工作与iOS 8.我所做的是创build我自己的UINavigationController的子类用于该popup窗口,并以这种方式覆盖方法preferredContentSize

 - (CGSize)preferredContentSize { return [[self.viewControllers lastObject] preferredContentSize]; } 

此外,我没有在viewDidAppear中调用forcePopoverSize (由@krasnyk实现的方法),而是决定将一个viewController(显示popover)作为前面提到的导航(在popover中)的代理,

 -(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated 

一个传递viewController委托方法。 一个重要的事情,做一个UINavigationControllerDelegate方法forcePopoverSize是好的,如果你不需要该animation是平滑的,如果是这样做,然后把它留在viewDidAppear

我面临同样的问题,但是你不想在viewWillAppear或viewWillDisappear方法中设置内容。

 AirPrintController *airPrintController = [[AirPrintController alloc] initWithNibName:@"AirPrintController" bundle:nil]; airPrintController.view.frame = [self.view frame]; airPrintController.contentSizeForViewInPopover = self.contentSizeForViewInPopover; [self.navigationController pushViewController:airPrintController animated:YES]; [airPrintController release]; 

在将该控制器推送到navigationController之前,为该控制器设置contentSizeForViewInPopover属性

我有幸把以下内容放在视图中:

 [self.popoverController setPopoverContentSize:self.contentSizeForViewInPopover animated:NO]; 

虽然在推动/popup不同大小的popup窗口的情况下,这可能不会很好地animation。 但在我的情况下,完美的作品!

所有你需要做的是:

在popOver contentView的viewWillAppear方法中,添加下面给出的代码片段。 加载时,您必须首次指定popOver的大小。

 CGSize size = CGSizeMake(width,height); self.contentSizeForViewInPopover = size; 

我有一个popoverContentSize = CGSizeMake(320,600)在开始的popover控制器的问题,但在浏览其ContentViewController(UINavigationController)时会变大。

导航控制器只是推和popup自定义UITableViewControllers,所以在我的自定义表视图控制器类的viewDidLoad我设置self.contentSizeForViewInPopover = CGSizeMake(320,556)

less了44个像素来解释导航控制器的导航栏,现在我没有任何问题了。

把它放在popover里面的所有视图控制器中

 CGSize currentSetSizeForPopover = CGSizeMake(260, 390); CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f, currentSetSizeForPopover.height - 1.0f); self.contentSizeForViewInPopover = fakeMomentarySize; self.contentSizeForViewInPopover = currentSetSizeForPopover; 

面对同样的问题,并通过在放置UIPopoverController的init之前将内容视图大小设置为导航控制器和视图控制器来修复它。

  CGSize size = CGSizeMake(320.0, _options.count * 44.0); [self setContentSizeForViewInPopover:size]; [self.view setFrame:CGRectMake(0.0, 0.0, size.width, size.height)]; [navi setContentSizeForViewInPopover:size]; _popoverController = [[UIPopoverController alloc] initWithContentViewController:navi]; 

我只是想提供另一种解决scheme,因为这些都为我工作…

我实际上使用这个https://github.com/nicolaschengdev/WYPopoverController

当你第一次打电话popup使用这个。

 if ([sortTVC respondsToSelector:@selector(setPreferredContentSize:)]) { sortTVC.preferredContentSize = CGSizeMake(popoverContentSortWidth, popoverContentSortHeight); } else { sortTVC.contentSizeForViewInPopover = CGSizeMake(popoverContentSortWidth, popoverContentSortHeight); } 

然后在这个popup使用这个。

 -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:YES]; if ([self respondsToSelector:@selector(setPreferredContentSize:)]) { self.preferredContentSize = CGSizeMake(popoverContentMainWidth, popoverContentMainheight); } else { self.contentSizeForViewInPopover = CGSizeMake(popoverContentMainWidth, popoverContentMainheight); } } -(void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:YES]; self.contentSizeForViewInPopover = CGSizeZero; } 

然后重复儿童的意见…

这是在iOS7中这样做的正确方法,在导航堆栈中的每个视图控制器中的viewDidLoad中设置首选内容大小(仅执行一次)。 然后在viewWillAppear中获取对popover控制器的引用,并在那里更新contentSize。

 -(void)viewDidLoad:(BOOL)animated { ... self.popoverSize = CGSizeMake(420, height); [self setPreferredContentSize:self.popoverSize]; } -(void)viewWillAppear:(BOOL)animated { ... UIPopoverController *popoverControllerReference = ***GET REFERENCE TO IT FROM SOMEWHERE***; [popoverControllerReference setPopoverContentSize:self.popoverSize]; } 

@krasnyk解决scheme在以前的iOS版本中运行良好,但不适用于iOS8。 以下解决scheme为我工作。

  - (void) forcePopoverSize { CGSize currentSetSizeForPopover = self.preferredContentSize; //Yes, there are coupling. We need to access the popovercontroller. In my case, the popover controller is a weak property in the app's rootVC. id mainVC = [MyAppDelegate appDelegate].myRootVC; if ([mainVC valueForKey:@"_myPopoverController"]) { UIPopoverController *popover = [mainVC valueForKey:@"_myPopoverController"]; [popover setPopoverContentSize:currentSetSizeForPopover animated:YES]; } } 

这不是最好的解决scheme,但它的工作原理。

新的UIPopoverPresentationController也有resize的问题:(。

您需要在viewWillAppear设置NavigationController的preferredContentSize属性:

 -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.navigationController.preferredContentSize = CGSizeMake(320, 500);}