UIPopoverController автоматически изменяет размер до максимальной высоты на pushViewController

У меня есть popover, содержащий UINavigationController. Я могу отобразить popover fine, и он содержит navController просто отлично. NavController содержит tableView, и когда я выбираю элемент, он создает новый подробный вид:

     DeviceDetailViewController *detailViewController = 
[[[DeviceDetailViewController alloc] initWithNibName:@"DeviceDetailViewController" bundle:nil] autorelease];

Затем я нажимаю на новый контроллер вида:

    [self.navigationController pushViewController:detailViewController animated:YES];

Это когда возникает проблема: после нажатия нового представления, popover изменяет размер до максимальной высоты, доступной на iPad.

Я попытался установить высоту всех представлений в xib на фиксированную высоту, а не на гибкость. Я попытался явно установить высоту popover. Я также попытался использовать разные контроллеры представлений в качестве дочернего представления. Проблема остается: popover хочет автоматически изменять размер до максимальной высоты всякий раз, когда новое представление переносится на контроллер навигации.

Здесь question, в котором обсуждается попытка преднамеренно контролировать размер popover при нажатии новых просмотров:

Я думал, что это может быть метод грубой силы для управления размером. Как ни странно, однако, это на самом деле вызывает некоторые быстрые графические причуды (как если бы представление было недавно анимированным), а затем продолжая изменять размер, как описано выше.

Другими словами, что-то буквально заставляет popover достигать максимальной высоты, и, похоже, это происходит после вызова всех методов-делегатов.

Это навигационный контроллер? Кто-нибудь видел такие вещи?

Ответ 1

Это исправило это для меня после того, как у меня была такая же проблема (совпадение также и сегодня):

EDIT. Поскольку contentSizeForViewInPopover устарел в iOS7.0, используйте preferredContentSize.

Оригинальный ответ ниже:

В detailViewController добавьте следующее:

- (void)viewWillAppear:(BOOL)animated {

    CGSize size = CGSizeMake(320, 480); // size of view in popover
    self.contentSizeForViewInPopover = size;

    [super viewWillAppear:animated];

}

Вы также хотите добавить что-то похожее на свой исходный DeviceDetailViewController, чтобы предотвратить изменение размера при нажатии на значок NavbarItem.

Ответ 2

Как и в случае с viewWillAppear, другой способ справиться с этим - переопределить contentSizeForViewInPopover. Очень краткий:

-(CGSize)contentSizeForViewInPopover
{
    return self.view.bounds.size;
}

Ответ 3

Для IOS5

Я рекомендую вам сделать это в:

- (void)viewDidLoad {
    [super viewDidLoad];

    CGSize size = CGSizeMake(320, 480); // size of view in popover
    self.contentSizeForViewInPopover = size;

}

Ответ 4

У меня была аналогичная проблема.

У меня появился popover из кнопки на панели инструментов. Попутчик был установлен в определенном размере. Это было табличное представление. Когда была выбрана строка таблицы, был вызван новый контроллер представления с контроллером навигации.

Когда была выбрана кнопка "Назад", popover стал размером по умолчанию (по-моему, 320x1100) вместо желаемого размера.

Исходный код:

  MyTableViewController *myVC = [[MyTableViewController alloc] init];
  UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myVC];

  UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController];
  popover.delegate = self;

  popover.popoverContentSize = CGSizeMake(400.0, 500.0);

  [myVC release];
  [navController release];
  [popover release];

Я добавил одну строку для решения проблемы. Конечно, это своего рода работа, потому что мне пришлось вычесть высоту заголовка. Возможно, один из вас мог бы просветить меня лучшим методом. Во всяком случае, он работает.

  MyTableViewController *myVC = [[MyTableViewController alloc] init];

  UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myVC];

  UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController];
  popover.delegate = self;

  popover.popoverContentSize = CGSizeMake(400.0, 500.0);

  //Subtract the height of the header to match the total popover size (not just the view).
  myVC.contentSizeForViewInPopover = CGSizeMake(400.0, 500-44);

  [myVC release];
  [navController release];
  [popover release];

Я считаю, что когда задействован контроллер навигации и нажата кнопка "Назад", это приводит к тому, что popover по умолчанию имеет свой размер по умолчанию. Добавив свойство contentSizeForViewInPopover для контроллера myVC, он заставляет определенный размер.

Надеюсь, что это будет полезно.

Курт

Ответ 5

Для iOS 7 используйте следующее:

- (void)viewDidLoad
{
    [super viewDidLoad];

    CGSize size = CGSizeMake(320, 768); // size of view in popover
    self.preferredContentSize = size;
}

UIViewController.contentSizeForViewInPopover был сначала устаревшим в iOS 7.

Ответ 6

В ответ на графические сбои с анимацией:

Анимации UIPopoverController конфликтуют с анимациями контроллеров UINavigation, если вы создаете popover с UINavigationController внутри него. Это приводит к графическим сбоям при анимации. Чтобы устранить проблему, установите анимированный параметр равным false при нажатии других контроллеров или при отображении панели инструментов.

Кнопки просмотра:

[self.navigationController pushViewController:detailViewController animated:NO];

Отображение панели инструментов:

[[self navigationController] setToolbarHidden:NO animated:NO]; 

Настройка анимированного: NO сделает анимацию правильной в UIPopoverController.

Ответ 7

Почему бы просто не установить contentSizeForViewInPopover, прежде чем нажимать следующий контроллер в стек навигации? Нет необходимости устанавливать размеры в viewWillAppear и т.д.

[nextController setContentSizeForViewInPopover:[self contentSizeForViewInPopover]];
[[self navigationController] pushViewController:nextController animated:YES];

Работает на IOS 5.1

Ответ 8

Незначительный параметр на совете borked (который указал мне в правильном направлении, спасибо за это!), вот что я делаю, когда вы нажимаете новый контроллер для поддержания размера до его нажатия:

productViewController.contentSizeForViewInPopover = self.view.bounds.size;
self.contentSizeForViewInPopover = self.view.bounds.size;

[self.navigationController pushViewController:productViewController animated:YES];

Мне это нравится, потому что мне не нужно жестко кодировать значения popover в каждом контроллере представления (хорошо, поскольку я использую их на разных высотах).

Строка self.contentSizeForViewInPopover предназначена для сохранения размера при ударе пользователя. Я думаю, вы могли бы поместить эту строку в другое место, например viewWillAppear или где угодно.

Кажется, работает...

Ответ 9

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

self setContentSizeForViewInPopover:CGSizeMake(320, 500)];

Ответ 10

Существует два способа установить contentSizeForViewInPopover в раскадровке. Вы можете настроить контроллеры представлений, которые находятся на вашем контроллере навигации, в FreeForm и установить корневые представления на требуемый размер. Или вы можете сохранить смоделированную метрику как выведенную и проверить "Использовать явный размер" и установить размер, который вы там хотите.

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

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

     ["yourpopoverController" setPopoverContentSize:CGSizeMake(self.
           contentSizeForViewInPopover.width, seld.contentSizeForViewInPopover.height + self.
           navigationController.navigationBar.frame.size.height) animated:YES];
}

В анимации перехода новый вид будет выровнен с верхним, а затем высота будет соответствующим образом скорректирована.

Таким образом, вам не нужно переопределять contentSizeForViewInPopover или указать какой-то другой размер, особенно в ваших контроллерах. Все это в раскадровке.

Если один из ваших контроллеров просмотров имеет переменную высоту, тогда вам необходимо переопределить contentSizeForViewInPopover в этом представлении, как это...

- (CGSize)contentSizeForViewInPopover {
    return CGSizeMake(450, "calculate your height here");
}

Ответ 11

Этот материал, возможно, работал один раз, но не с xCode 6, в котором contentSizeForViewInPopover устарел. К счастью, он соблюдал время загрузки раскадровки. Я загрузил xml-редактор (Xmplify) и взломал раскадровку. Установите ключ contentSizeForViewInPopover на нужный размер. Сохраните и замените (сделайте копию первой) раскадровкой.

Более конкретно:

< viewController>

     <value key="contentSizeForViewInPopover" type="size" width="450" height="280" / >

</viewController>

Ответ 12

Не работайте для меня, когда я использую это:

[UIPopoverController 
    [UINavigationController] = root vc = [UIViewController vc1] => [UIViewController vc2] 
]

Когда появится всплывающее окно, нажмите кнопку vc1 и нажмите vc2 на навигационный контроллер

Далее вернитесь к vc1 (root), нажав кнопку в vc2 (метод popToRootViewController);

Мы можем видеть, что popover изменяет собственный размер, но размер vc1 старый... ЧТО ЭТО???

Хорошо, теперь работа... Добавить свойство popover в мой контроллер

self.contentSizeForViewInPopover = (CGSize){400, 200};
self.navigationController.contentSizeForViewInPopover = self.contentSizeForViewInPopover;
self.popover.popoverContentSize = self.contentSizeForViewInPopover;

Ответ 13

Запуск Swift 4 и iOS 11 - единственное возможное решение для меня. Использовать showViewController:sender: and showDetailViewController:sender: вместо presentViewController:animated:completion:.

Из Apple Doc

Служба showViewController: sender: and showDetailViewController: sender: методы предлагают наиболее адаптивный и гибкий способ отображения контроллеров представлений. Эти методы позволяют контроллеру представления представления решать, как лучше всего обрабатывать презентацию. Например, контроллер представления контейнера может включать контроллер представления в качестве дочернего элемента вместо его представления в виде модально. Поведение по умолчанию представляет собой контроллер вида.