Подтвердить что ты не робот

UINavigationController в ViewController, разрыв в верхней части окна

Я работаю над универсальным приложением, и я пытаюсь использовать как можно больше кода между версиями iPhone и iPad. Мне нужно использовать TabBarController в качестве моего контроллера корневого представления, и хотя я бы хотел использовать SplitViewController на каждой вкладке, в документах SplitViewController говорится, что он должен быть контроллером корневого представления. Итак, имея в виду все это - поймите, что я пытаюсь разместить два навигационных контроллера бок о бок и (в основном) реплицировать поведение/компоновку SplitViewController.

Все работает отлично, за исключением макета представлений. Когда приложение запускается в портретном режиме, все работает и изменяет размер/положение правильно при изменении ориентации устройства.

portrait orientation

Если приложение запускается в любой ориентации, отличной от UIDeviceOrientationPortrait, представление отображается с 20-кратным разрывом/маркой над навигационным контроллером. Я попытался настроить фрейм во время выполнения без идеального результата. Корректировка начала. Frame of -20 и увеличение высоты на 20 приводит к тому, что изображение заподлицо с верхней частью его родителя, но оно оставляет 20-точечный зазор внизу!

landscape orientation

4b9b3361

Ответ 1

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

[parentView addSubview:navController.view];
[navController setNavigationBarHidden:YES];
[navController setNavigationBarHidden:NO];

Ответ 2

Как ни странно, то, что помогает мне в iOS 6, подклассифицирует UINavigationController и реализует этот метод:

- (BOOL)wantsFullScreenLayout {
    return NO;
}

Убрав флажок "Wants Full Screen" в моей раскадровке, это не помогло, поэтому я не знаю, что другое. Это, безусловно, может переломить будущую версию iOS. Но пока я это сделаю.

Ответ 3

UINavigationController обычно отображается как полноэкранный контроллер, что означает, что (когда отображается как контроллер корневого представления окна) верхняя часть его представления помещается под панель состояния. Затем он вручную позиционирует свою навигационную панель и просмотр содержимого, чтобы не перекрывать строку состояния, когда отображается строка состояния. К сожалению, на самом деле он не справляется правильно, когда он позиционируется каким-то другим контроллером представлений, он (иногда) предполагает, что ему нужно оставить этот пробел в 20 пикселей, не проверяя, находится ли его представление на самом деле в строке состояния.

Решение состоит в том, чтобы установить wantsFullScreenLayout на UINavigationController на NO, поэтому он даже не попытается оставить этот пробел для строки состояния.

Ответ 4

Я смог выполнить грубую силу следующим образом. В viewDidLoad или loadView:

if (self.navigationController.navigationBar.frame.origin.y > 0.0) {
    self.navigationController.navigationBar.frame = CGRectOffset(self.navigationController.navigationBar.frame, 0.0, -20.0);
}

И в viewDidAppear:

if (self.view.superview.frame.origin.y > 44.0) {
    UIView *container = self.view.superview;
    container.frame = CGRectMake(container.frame.origin.x, container.frame.origin.y - 20.0, container.frame.size.width, container.frame.size.height + 20.0);
}

Это некрасиво, но, похоже, это работает.

Ответ 5

Чтобы устранить эту проблему, установите флажок Wants Full Screen на раскадровке.

Проблема возникает из-за того, что в строке ParentViewController отображается панель навигации.

Как сказано в документации Apple:

Если ваше приложение отображает строку состояния, представление сжимается, чтобы оно не перекрывало строку состояния. В конце концов, если строка состояния непрозрачна, нет никакого способа увидеть или взаимодействовать с содержимым, лежащим под ним. Однако, если ваше приложение отображает полупрозрачную строку состояния, вы можете установить, что значение вашего контроллера представления хочет, чтобы свойство FullScreenLayout было YES, чтобы ваше представление отображалось в полноэкранном режиме. Строка состояния рисуется над верхней частью представления.

Ответ 6

Не уверен, будет ли это какой-либо помощи, но у меня были подобные проблемы в прошлом, и я смог решить эту проблему, установив фрейм представления UINavigationController на CGRectZero, добавив его в свой супервизор.

В layoutSubviews я, конечно, обновляю рамку представления UINavigationController.

Ответ 7

Это обычная проблема при добавлении контроллеров представлений в панель вкладок.

Из документации Apple (Контроллеры панели вкладок - вкладки и полноэкранный макет):

Контроллеры панели управления поддерживают полноэкранную компоновку, отличную от той, которую поддерживают большинство других контроллеров. Вы все равно можете установить для свойства needsFullScreenLayout вашего настраиваемого контроллера представлений YES, если вы хотите, чтобы его представление перекрывало строку состояния или панель навигации (если она есть). Однако установка этого свойства в значение "ДА" не приводит к тому, что представление перекрывает представление панели вкладок. Контроллер панели вкладок всегда изменяет размеры вашего представления, чтобы предотвратить его подслоение панели вкладок.

В словах кода вы должны сделать следующее:

UINavigationController *myNavController = [[UINavigationView alloc] init];
myNavController.wantsFullScreenLayout = YES;

//...

NSArray* controllers = [NSArray arrayWithObjects:myNavController, nil];
myTabBarController.viewControllers = controllers;

Если однако, возникает проблема, заключающаяся в том, что при открытии приложения в ориентации, отличном от UIInterfaceOrientationPortrait, ваше представление myNavController перемещает 20 пикселей с экрана на верх, тогда вы установите контроллер wantsFullScreenLayout динамически (вместо указанного выше решения), в зависимости от начальной ориентации. Я делаю это, используя статическую переменную, определенную в вашей реализации контроллера навигации:

static UIInterfaceOrientation _initialOrientation = -1;

После этого вам нужно перегрузить метод viewDidAppear: и соответствующим образом установить переменную:

- (void)viewDidAppear:(BOOL)animated
{
  if (_initialOrientation == -1)
    _initialOrientation = [[UIApplication sharedApplication] statusBarOrientation];
  self.wantsFullScreenLayout = (_initialOrientation != UIInterfaceOrientationPortrait);

  [super viewDidAppear:animated];
}

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

Ответ 8

Я столкнулся с той же проблемой при добавлении UITableView в свой ViewController в viewDidLoad. Вместо того, чтобы захватить рамку из self.view, я получил ее в главном окне, чтобы она выглядела как

UIWindow *keyWindow = [[[UIApplication sharedApplication] delegate] window];
self.uiTable = [[UITableView alloc] initWithFrame:[keyWindow frame] style:UITableViewStylePlain];

Ответ 9

имела аналогичную проблему с нежелательным разрывом между строкой состояния и представлением непосредственно below, она решила его, перейдя в autosizing в построителе интерфейсов и установив рассматриваемое представление, чтобы придерживаться верхней части его родительского представления,

Ответ 10

По моему мнению, это отображается внутри навигационного контроллера, я помещаю этот код внутри viewDidAppear

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

    // START OF BUG FIX FOR iOS
if (self.navigationController.navigationBar.frame.origin.y ==20) {
    // Move the navigation Bar up
    [self.navigationController.navigationBar setFrame:CGRectMake(0, 0, self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height)];
    // move up the table view
     [self.view setFrame:CGRectMake(0, -20, self.view.frame.size.width, self.view.frame.size.height+20)];
}
// END OF BUG FIX for IOS6

Ответ 11

Правильный ответ:

CGRect r = [[_navController view] frame];
r.origin = CGPointMake(0.0f, -20.0f);
[[_navController view] setFrame:r];