UINavigationController внутри ViewController, пробел в верхней части представления - PullRequest
19 голосов
/ 03 марта 2011

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

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

portrait orientation

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

landscape orientation

Ответы [ 11 ]

25 голосов
/ 02 декабря 2011

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

[parentView addSubview:navController.view];
[navController setNavigationBarHidden:YES];
[navController setNavigationBarHidden:NO];
16 голосов
/ 17 ноября 2012

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

- (BOOL)wantsFullScreenLayout {
    return NO;
}

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

3 голосов
/ 28 февраля 2013

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

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

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

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

3 голосов
/ 17 марта 2011

Мне удалось грубой силой следующим образом. В viewDidLoad или loadView:

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

А в представлении DidAppear:

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);
}

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

3 голосов
/ 03 марта 2011

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

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

2 голосов
/ 20 сентября 2013

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

UIWindow *keyWindow = [[[UIApplication sharedApplication] delegate] window];
self.uiTable = [[UITableView alloc] initWithFrame:[keyWindow frame] style:UITableViewStylePlain];
2 голосов
/ 23 ноября 2011

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

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

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

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

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

//...

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

If, однако , вы сталкиваетесь с проблемой, заключающейся в том, что при открытии приложения с ориентацией, отличной от 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];
}

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

2 голосов
/ 26 августа 2011

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

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

0 голосов
/ 29 января 2013

На мой взгляд, который отображается внутри контроллера навигации, я поместил этот код в 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
0 голосов
/ 24 июля 2012
У

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...