У меня есть UIPopoverController, на котором размещен UINavigationController, который содержит небольшую иерархию диспетчеров представлений.
Я следил за документами и для каждого контроллера представления, я установил размер popover-context вида так:
[self setContentSizeForViewInPopover:CGSizeMake(320, 500)];
(размер отличается для каждого контроллера)
Это работает, как и ожидалось, когда я перемещаюсь по иерархии: popover автоматически анимирует изменения размера, соответствующие толкаемому контроллеру.
Однако, когда я перемещаюсь по "Назад" через стек представления с помощью кнопки "Назад" навигационной панели, popover не изменяет размер - он остается таким же большим, как и самый глубокий вид. Это кажется мне сломленным; Я ожидаю, что popover будет уважать размеры, которые настраиваются по мере того, как они появляются через стек представления.
Я что-то пропустил?
Спасибо.
Ответ 1
Хорошо, я боролся с той же проблемой. Ни одно из вышеперечисленных решений не работало для меня довольно красиво, поэтому я решил провести небольшое расследование и выяснить, как это работает.
Это то, что я обнаружил:
- Когда вы устанавливаете contentSizeForViewInPopover
в своем контроллере просмотра, он не будет изменен самим popover - хотя размер popover может измениться при навигации к другому контроллеру.
- Когда размер popover будет меняться при навигации к другому контроллеру, возвращаясь назад, размер popover не восстанавливается
- Изменение размера popover в viewWillAppear дает очень странную анимацию (когда вы говорите, что вы popController внутри popover) - я бы не рекомендовал его
- Для меня установка жестко заданного размера внутри контроллера не будет работать вообще - мои контроллеры должны быть иногда большими, иногда небольшими - контроллер, который будет их представлять, имеет представление о размере, хотя
Решение для всей этой боли выглядит следующим образом:
Вы должны reset размер currentSetSizeForPopover
в viewDidAppear. Но вы должны быть осторожны, когда вы установите тот же размер, который был уже установлен в поле currentSetSizeForPopover
, тогда попсор не изменит размер. Чтобы это произошло, вы можете сначала установить поддельный размер (который будет отличаться от того, который был установлен ранее), а затем установить правильный размер. Это решение будет работать, даже если ваш контроллер вложен в контроллер навигации, и 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
требуемого контроллера.
Ответ 2
Вот как я решил это для 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
Ответ 3
Это улучшение в ответе krasnyk.
Ваше решение отлично, но оно не плавно анимировано.
Небольшое улучшение дает приятную анимацию:
Удалить последнюю строку в методе - (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;
}
Ответ 4
Вам нужно снова установить размер содержимого в viewWillAppear
. Вызвав метод delagate, в котором вы задаете размер popovercontroller. У меня была та же проблема. Но когда я добавил, проблема решена.
Еще одна вещь: если вы используете бета-версии, меньшие, чем 5. Тогда поппостерам сложнее управлять. Они, похоже, более дружелюбны с бета-версией 5. Хорошо, что окончательная версия отсутствует.;)Забастовкa >
Надеюсь, что это поможет.
Ответ 5
В -(void)viewDidLoad
всех контроллеров вида, которые вы используете в контроллере навигации, добавьте:
[self setContentSizeForViewInPopover:CGSizeMake(320, 500)];
Ответ 6
I reset размер в анимационном методе viewWillDisappear: (BOOL) контроллера вида, который перемещается назад:
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
CGSize contentSize = [self contentSizeForViewInPopover];
contentSize.height = 0.0;
self.contentSizeForViewInPopover = contentSize;
}
Затем, когда появится представление, отображаемое назад, я reset размер соответственно:
-(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;
}
Ответ 7
Для 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...
Ответ 8
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 !
Ответ 9
Для меня эти решения работают.
Это метод из моего контроллера представления, который расширяет 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];
}
Ответ 10
если вы можете представить assambler, я думаю, что это немного лучше:
- (void) forcePopoverSize {
CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover;
self.contentSizeForViewInPopover = CGSizeMake(0, 0);
self.contentSizeForViewInPopover = currentSetSizeForPopover;
}
Ответ 11
Ответ на не работает отлично с 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
.
Ответ 12
У меня возникла такая же проблема, но вы не хотите устанавливать контент в 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
Ответ 13
Мне повезло, поставив следующее в viewdidappear:
[self.popoverController setPopoverContentSize:self.contentSizeForViewInPopover animated:NO];
Хотя это может не приятно анимироваться в случае, когда вы нажимаете/выскакиваете по-разному по-разному. Но в моем случае отлично работает!
Ответ 14
Все, что вам нужно сделать, это:
- В методе viewWillAppear для popover контента popOvers добавьте приведенный ниже фрагмент. Сначала вам нужно будет указать размер popOver, когда он будет загружен.
CGSize size = CGSizeMake(width,height);
self.contentSizeForViewInPopover = size;
Ответ 15
У меня возникла эта проблема с контроллером popover, чья popoverContentSize = CGSizeMake (320, 600) в начале, но будет больше при навигации через ContentViewController (UINavigationController).
Контроллер nav только выталкивал и выталкивал пользовательские UITableViewControllers, поэтому в моем настраиваемом представлении таблиц контроллера класса viewDidLoad я установил self.contentSizeForViewInPopover = CGSizeMake (320, 556)
44 меньше пикселей должны учитывать навигационную панель Nav controller, и теперь у меня больше нет проблем.
Ответ 16
Поместите это во все контроллеры просмотра, которые вы нажимаете внутри popover
CGSize currentSetSizeForPopover = CGSizeMake(260, 390);
CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f,
currentSetSizeForPopover.height - 1.0f);
self.contentSizeForViewInPopover = fakeMomentarySize;
self.contentSizeForViewInPopover = currentSetSizeForPopover;
Ответ 17
Столкнулась с той же проблемой и исправила ее, установив размер представления контента на контроллер навигации и контроллер представления до того, как была помещена инициация 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];
Ответ 18
Я просто хотел бы предложить другое решение, так как никто из них не работал у меня...
Я использую его с помощью 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;
}
Затем повторите для дочерних просмотров...
Ответ 19
Это правильный способ в 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];
}
Ответ 20
Решение @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 rootVC.
id mainVC = [MyAppDelegate appDelegate].myRootVC;
if ([mainVC valueForKey:@"_myPopoverController"]) {
UIPopoverController *popover = [mainVC valueForKey:@"_myPopoverController"];
[popover setPopoverContentSize:currentSetSizeForPopover animated:YES];
}
}
Это не лучшее решение, но оно работает.
Новый UIPopoverPresentationController также имеет проблему изменения размера:(.
Ответ 21
Вам нужно установить свойство preferredContentSize
для NavigationController в viewWillAppear
:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.preferredContentSize = CGSizeMake(320, 500);}