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