У меня есть UIPopoverController, на котором размещен UINavigationController, который содержит небольшую иерархию контроллеров представления.
Я следил за документами и для каждого контроллера представления я установил размер всплывающего контекста представления следующим образом:
[self setContentSizeForViewInPopover:CGSizeMake(320, 500)];
(размер разный для каждого контроллера)
Это работает так, как ожидалось, когда я двигаюсь вперед по иерархии - всплывающее окно автоматически анимирует изменения размера в соответствии с нажатым контроллером.
Однако, когда я перемещаюсь «Назад» по стеку представлений с помощью кнопки «Назад» на панели навигации, всплывающее окно не меняет размер - оно остается таким же большим, как и самый глубокий просмотр. Мне это кажется сломанным; Я ожидал, что всплывающее окно будет уважать размеры, которые установлены при просмотре стека представлений.
Я что-то упускаю?
Спасибо.
viewWillAppear:
)?Ответы:
Хорошо, я боролся с той же проблемой. Ни одно из вышеперечисленных решений не сработало для меня достаточно хорошо, поэтому я решил провести небольшое расследование и выяснить, как это работает. Вот что я обнаружил: - Когда вы устанавливаете
contentSizeForViewInPopover
в вашем контроллере представления он не будет изменен самим всплывающим окном, хотя размер всплывающего окна может измениться при переходе к другому контроллеру. - Когда размер всплывающего окна изменится при переходе к другому контроллеру, при возврате размер всплывающего окна не восстанавливается - Изменение размера всплывающего окна в viewWillAppear дает очень странную анимацию (когда, скажем, вы popController внутри всплывающего окна) - Я бы не рекомендовал это - для меня установка жестко запрограммированного размера внутри контроллера вообще не будет работать - мои контроллеры должны быть иногда большими, иногда маленькими - контроллер, который представит им, имеет представление о размере, хотяРешение для всей этой боли заключается в следующем: вам нужно сбросить размер
currentSetSizeForPopover
в viewDidAppear. Но вы должны быть осторожны, когда вы установите тот же размер, который уже был установлен в поле,currentSetSizeForPopover
всплывающее окно не изменит размер. Чтобы это произошло, вы можете сначала установить поддельный размер (который будет отличаться от того, который был установлен ранее), а затем установить правильный размер. Это решение будет работать, даже если ваш контроллер вложен в контроллер навигации, и всплывающее окно изменит свой размер соответствующим образом, когда вы вернетесь между контроллерами.Вы можете легко создать категорию в 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 незаметно оборачивает представление, которое вы хотите во всплывающем окне, в представленный ViewController контроллера представления PresentingViewController. Есть видео WWDC 2014 года, объясняющее, что нового в popovercontroller, где они касаются этого.
В любом случае, для контроллеров представления, представленных в стеке контроллеров навигации, которые все хотят иметь собственный размер, этим контроллерам представления необходимо (в iOS 8) вызывать этот код для динамической установки предпочитаемогоContentSize:
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
источник
presentingViewController
работами. Если я устанавливаюpreferredContentSize
in,viewDidLoad
происходит странное поведение: переход назад с другого контроллера представления в всплывающем окне приводит к неправильному изменению размера всплывающего окна. Похоже, что размер всплывающего окна равен нулю, но размер правильный. В этом случае всплывающее окно занимает всю высоту экрана. Вы знаете, может быть, почему это так? У меня нет ограничения в 600 точек, потому что, по моему опыту, операционная система не позволяет указывать размер больше, чем размер экрана.viewDidLoad
...Это улучшение ответа Красника .
Ваше решение отличное, но оно не анимировано плавно.
Небольшое улучшение дает приятную анимацию:
Удалите последнюю строку в
- (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 они кажутся более дружелюбными. Хорошо, что финальная версия вышла. ;)Надеюсь это поможет.
источник
viewWillAppear
у меня не сработала. Явная установка размера всплывающего окна действительно сработала, но это гетто.Во
-(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 ...
источник
willTransitionToTraitCollection
вanimateAlongsideTransition
блоке завершения.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]; }
источник
если вы можете представить себе ассамблера, я думаю, это немного лучше:
источник
CGSizeZero
вместо того, чтобы делать это самостоятельноCGSizeMake(0,0)
Общепринятый ответ не работает нормально с прошивкой 8. То , что я сделал создавал свой собственный подкласс
UINavigationController
для использования в этом и пироге переопределить методpreferredContentSize
следующим образом:- (CGSize)preferredContentSize { return [[self.viewControllers lastObject] preferredContentSize]; }
Более того, вместо вызова
forcePopoverSize
(метода, реализованного @krasnyk) вviewDidAppear
я решил установить viewController (который показывает всплывающее окно) в качестве делегата для ранее упомянутой навигации (в всплывающем окне) и сделать (что делает метод force) в:-(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 для popOvers contentView добавьте фрагмент, указанный ниже. Вам нужно будет указать размер popOver в первый раз при его загрузке.
CGSize size = CGSizeMake(width,height); self.contentSizeForViewInPopover = size;
источник
У меня была эта проблема с контроллером всплывающего окна, у которого popoverContentSize = CGSizeMake (320, 600) в начале, но он увеличивался при навигации через его ContentViewController (UINavigationController).
Контроллер навигации только нажимал и выдвигал пользовательские UITableViewControllers, поэтому в моем классе контроллера пользовательского табличного представления viewDidLoad я установил self.contentSizeForViewInPopover = CGSizeMake (320, 556)
На 44 пикселя меньше приходится на панель навигации контроллера навигации, и теперь у меня больше нет проблем.
источник
Поместите это во все контроллеры представления, которые вы нажимаете внутри всплывающего окна
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 получите ссылку на контроллер всплывающего окна и обновите там 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);}
источник