Popover со встроенным навигационным контроллером не учитывает размер на заднем навигаторе

У меня есть UIPopoverController, на котором размещен UINavigationController, который содержит небольшую иерархию контроллеров представлений.

Я следил за документами и для каждого контроллера представления, я установил размер popover-контекста вида следующим образом:

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

(размер отличается для каждого контроллера)

Это работает так, как я ожидал, когда я перемещаюсь вперед в иерархии – popover автоматически анимирует изменения размера, соответствующие толкаемому контроллеру.

Однако, когда я перемещаюсь «назад» через стек представления через кнопку «Назад» на панели навигации, popover не меняет размер – он остается таким же большим, как и самый глубокий вид. Это кажется мне сломленным; Я ожидаю, что popover будет уважать размеры, которые настроены, когда он появляется через стек представления.

Я что-то упускаю?

Благодарю.

21 Solutions collect form web for “Popover со встроенным навигационным контроллером не учитывает размер на заднем навигаторе”

Хорошо, я боролся с той же проблемой. Ни одно из вышеперечисленных решений не работало для меня довольно красиво, поэтому я решил провести небольшое расследование и выяснить, как это работает. Это то, что я обнаружил: – Когда вы устанавливаете contentSizeForViewInPopover в своем контроллере просмотра, он не будет изменен самим popover – хотя размер popover может измениться при навигации к другому контроллеру. – Когда размер popover будет меняться при навигации к другому контроллеру, при возврате размер popover не восстанавливается. – Изменение размера popover в viewWillAppear дает очень странную анимацию (скажем, вы popController внутри popover) – Я бы не рекомендовал его – для меня установка жестко заданного размера внутри контроллера не будет работать вообще – мои контроллеры должны быть иногда большими, иногда небольшими – контроллер, который будет их представлять, имеет представление о размере, хотя

Решение для всей этой боли выглядит следующим образом: вы должны сбросить размер currentSetSizeForPopover в viewDidAppear. Но вы должны быть осторожны, когда вы установите тот же размер, который уже был установлен в поле currentSetSizeForPopover тогда popover не изменит размер. Чтобы это произошло, вы можете сначала установить поддельный размер (который будет отличаться от того, который был установлен ранее), а затем установить правильный размер. Это решение будет работать, даже если ваш контроллер вложен в контроллер навигации, и popover изменит его размер соответственно, когда вы будете перемещаться между контроллерами.

Вы можете легко создать категорию в UIViewController со следующим вспомогательным методом, который бы сделал трюк с настройкой размера:

 - (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 молча переносит представление, которое вы хотите в popover, в представленный контроллер управления представлением viewController. Есть видеоролик WWDC 2014 года, в котором объясняется, что нового с контроллером popover, где они касаются этого.

В любом случае, для контроллеров представлений, представленных в стеке контроллера навигации, которые все хотят иметь собственный размер, эти диспетчеры представлений нуждаются (под iOS 8), чтобы вызвать этот код, чтобы динамически установить preferredContentSize:

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

Замените heightOfTable на вычисленную таблицу или высоту просмотра.

Чтобы избежать большого количества дубликатов кода и создания общего решения iOS 7 и iOS 8, я создал категорию в UITableViewController для выполнения этой работы, когда 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 

Это улучшает ответ Красника .
Ваше решение отлично, но оно не плавно анимируется.
Небольшое улучшение дает приятную анимацию:

Удалите последнюю строку в методе - (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 { [super viewDidAppear:animated]; CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover; self.contentSizeForViewInPopover = currentSetSizeForPopover; } 

Вам нужно снова установить размер содержимого в viewWillAppear . Вызвав метод delagate, в котором вы задаете размер popovercontroller. У меня была та же проблема. Но когда я добавил, проблема решена.

Еще одна вещь: если вы используете бета-версии, меньшие, чем 5. Тогда поппостерам сложнее управлять. Они, похоже, более дружелюбны с бета-версией 5. Хорошо, что окончательная версия отсутствует. 😉

Надеюсь это поможет.

В представлении -(void)viewDidLoad всех контроллеров представлений, которые вы используете в контроллере навигации, добавьте:

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

Я сбрасываю размер в анимационном методе viewWillDisappear: (BOOL) контроллера вида, который перемещается обратно:

 -(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 ! 

Для меня это решение работает. Это метод из моего контроллера представления, который расширяет 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]; } 

если вы можете вообразить assambler, я думаю, что это немного лучше:

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

Принятый ответ не работает нормально с iOS 8. Что я сделал, так это создание моего собственного подкласса UINavigationController для использования в этом popover и переопределить метод preferredContentSize таким образом:

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

Более того, вместо вызова forcePopoverSize (метод, реализованный @krasnyk) в viewDidAppear я решил установить viewController (который показывает popover) в качестве делегата для ранее упомянутой навигации (в popover) и делать (что делает метод силы) в:

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

метод делегата для прошедшего viewController . Одна важная вещь, выполняющая forcePopoverSize в методе UINavigationControllerDelegate является прекрасной, если вам не нужна эта анимация, чтобы она была гладкой, если так, то оставите ее в 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]; 

установите свойство contentSizeForViewInPopover для этого контроллера, прежде чем нажимать этот контроллер на navigationController

Мне повезло, добавив следующее в viewdidappear:

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

Хотя это может не приятно анимировать в случае, когда вы нажимаете / выскакиваете поп-роли разного размера. Но в моем случае, отлично работает!

Все, что вам нужно сделать, это:

-В методе viewWillAppear для popover контента popOvers добавьте приведенный ниже фрагмент. Сначала вам нужно будет указать размер popOver при его загрузке.

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

У меня была эта проблема с контроллером popover, popoverContentSize = CGSizeMake (320, 600) с самого начала, но он будет увеличиваться при навигации через ContentViewController (UINavigationController).

Контроллер nav только выталкивал и выталкивал пользовательские UITableViewControllers, поэтому в моем настраиваемом представлении класса TableView viewDidLoad я установил self.contentSizeForViewInPopover = CGSizeMake (320, 556)

44 меньше пикселей должны учитывать навигационную панель контроллера Nav, и теперь у меня больше нет проблем.

Поместите это во все контроллеры просмотра, которые вы нажимаете внутри popover

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

Столкнулась с той же проблемой и исправила ее, установив размер представления контента на контроллер навигации и контроллер представления до того, как была установлена ​​инициализация UIPopoverController.

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

Я просто хотел бы предложить другое решение, так как никто из них не работал для меня …

Я на самом деле использую его с этим https://github.com/nicolaschengdev/WYPopoverController

Когда вы впервые вызываете свое всплывающее окно, используйте это.

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

Затем в этом всплывающем меню используйте это.

 -(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 хорошо работало в предыдущих версиях iOS, но не работало в iOS8. Для меня работало следующее решение.

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

Это не лучшее решение, но оно работает.

Новый UIPopoverPresentationController также имеет проблему изменения размера :(.

Вам необходимо установить свойство preferredContentSize для NavigationController в viewWillAppear :

 -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.navigationController.preferredContentSize = CGSizeMake(320, 500);} 
  • Проблемы с xcode при поступлении с другого контроллера представления
  • Автоматическая компоновка детского контейнера, встраивающего UIViewController
  • Рамка uitableview не изменяется программно
  • Разрешить авторотацию только на одном контроллере представления
  • Неправильная рамка при отклонении модально представленного контроллера представления
  • popoverPresentationController, отображающий модально с UITableViewController на iPhone
  • изменить return from shouldAutorotateToInterfaceOrientation: at runTime
  • Можем ли мы получить массив всех представлений раскадровки
  • Устранение отклоненияViewControllerAnimated не работает в блоке
  • как сделать прозрачным прозрачный контроллер вида
  • новые ViewControllers, вызывающие черный экран
  • Interesting Posts

    Получение данных ответа сканирования Bluetooth LE с помощью iOS

    Как ограничить число десятичных точек в UITextField?

    Ошибка отправки почтового запроса HTTP с изображением

    Как вручную отправить следующий сигнал наблюдаемому в RxSwift?

    Способ сохранения объектов MPMediaItemCollection? (выбирается из iPod)

    Отладка родных приложений iOS, на Mac-машине в облаке, через локальный USB-порт

    Скрытие клавиатуры нажатием кнопки?

    Как ограничить символы в UITextView?

    Создание iOS build / ipa больше не работает из командной строки

    Возможно ли разработать приложение для iMac, которое переносится на iPad?

    создание GLView из представления в банке

    Xcode 9 GM Simulator Screen Artefacts

    Передайте значение из одного ViewController в другое в Objective-C

    Невозможно получить доступ к индексу элемента tabBar с помощью swift.

    IOS: UIWebView: миниатюра видео youtube не подходит внутри UIWebview

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.