Строка состояния и панель навигации отображаются за пределами моего представления в iOS 7
Я недавно загрузил Xcode 5 DP для тестирования своих приложений в iOS 7. Первое, что я заметил и подтвердил, это то, что границы моего представления не всегда изменяются с учетом строки состояния и панели навигации.
В viewDidLayoutSubviews
Я печатаю границы представления:
{{0, 0}, {320, 568}}
В результате мой контент появляется под панелью навигации и строкой состояния.
Я знаю, что могу сам рассчитать высоту, получив высоту главного экрана, вычтя высоту строки состояния и высоту панели навигации, но это кажется ненужной дополнительной работой.
Как я могу исправить эту проблему?
Обновить:
Я нашел решение для этой конкретной проблемы. Установите для полупрозрачного свойства панели навигации значение NO:
self.navigationController.navigationBar.translucent = NO;
Это предотвратит отображение вида под панелью навигации и строкой состояния.
Однако я не нашел исправления для случая, когда вы хотите, чтобы панель навигации была полупрозрачной. Например, при просмотре фотографии в полноэкранном режиме, я хочу, чтобы панель навигации была полупрозрачной, а вид под ней был обрамлен. Это работает, но когда я переключаю показ / скрытие панели навигации, я получаю еще более странные результаты. Первое подпредставление (UIScrollView) получает свои границы и происхождение меняется каждый раз.
20 ответов
Вы можете добиться этого, внедрив новое свойство под названием edgesForExtendedLayout
в iOS7 SDK. Пожалуйста, добавьте следующий код для достижения этой цели,
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
Вы должны добавить выше в вашем -(void)viewDidLoad
метод.
В iOS 7 внесены некоторые изменения в макет и настройку внешнего вида вашего пользовательского интерфейса. Изменения в макете контроллера представления, цвете оттенка и шрифте влияют на все объекты UIKit в вашем приложении. Кроме того, усовершенствования API распознавания жестов обеспечивают более точный контроль над взаимодействиями жестов.
Использование контроллеров представления
В iOS 7 контроллеры представления используют полноэкранное расположение. В то же время, iOS 7 дает вам более детальный контроль над тем, как контроллер представления размещает свои представления. В частности, концепция полноэкранного макета была усовершенствована, чтобы позволить контроллеру представления указывать макет каждого края своего представления.
wantsFullScreenLayout
свойство контроллера представления устарело в iOS 7. Если вы в настоящее время указываетеwantsFullScreenLayout = NO
Контроллер представления может отображать свой контент в неожиданном месте на экране, когда он работает в iOS 7.Чтобы настроить, как контроллер представления выкладывает свои представления,
UIViewController
предоставляет следующие свойства:
- edgesForExtendedLayout
edgesForExtendedLayout
свойство используетUIRectEdge
тип, который определяет каждое из четырех ребер прямоугольника, в дополнение к указанию none и all. использованиеedgesForExtendedLayout
указать, какие края вида должны быть расширены, независимо от прозрачности полосы. По умолчанию значение этого свойстваUIRectEdgeAll
,
- extendedLayoutIncludesOpaqueBars
Если ваш дизайн использует непрозрачные бары, уточните
edgesForExtendedLayout
также установивextendedLayoutIncludesOpaqueBars
собственности на нет. (Значение по умолчаниюextendedLayoutIncludesOpaqueBars
это НЕТ.)
- automaticallyAdjustsScrollViewInsets
Если вы не хотите, чтобы вставки содержимого представления прокрутки автоматически настраивались, установите
automaticallyAdjustsScrollViewInsets
в NO. (Значение по умолчаниюautomaticallyAdjustsScrollViewInsets
это ДА.)
- topLayoutGuide, bottomLayoutGuide
topLayoutGuide
а такжеbottomLayoutGuide
свойства указывают расположение верхней или нижней кромок панели в представлении контроллера представления. Если столбцы должны перекрывать верхнюю или нижнюю часть представления, вы можете использовать Интерфейсный Разработчик, чтобы расположить представление относительно панели, создавая ограничения в нижней части окна.topLayoutGuide
или к вершине bottomLayoutGuide. (Если ни один столбец не должен перекрывать вид, нижняя частьtopLayoutGuide
такой же, как верхняя часть вида и верхняя частьbottomLayoutGuide
совпадает с нижней частью представления.) Оба свойства лениво создаются по запросу.
Пожалуйста, обратитесь, Apple Doc
Вам не нужно вычислять, как далеко все сдвинуть вниз, для этого есть встроенное свойство. В Интерфейсном Разработчике выделите ваш контроллер представления, а затем перейдите к инспектору атрибутов. Здесь вы увидите несколько флажков со словами "Расширить края". Как вы можете видеть, на первом снимке экрана выбор по умолчанию - отображение контента под верхней и нижней полосами, а не под непрозрачными полосами, поэтому настройка стиля полосы на непрозрачный работает для вас.
Как вы можете увидеть на первом скриншоте, под панелью навигации скрываются два элемента пользовательского интерфейса. (Я включил каркасы в IB, чтобы проиллюстрировать это). Эти элементы, UIButton и UISegmentedControl, имеют свое начало "y", установленное в ноль, и контроллер представления установлен, чтобы разрешить содержание ниже верхней панели.
Этот второй снимок экрана показывает, что происходит, когда вы снимаете флажок "Under Top Bars". Как вы можете видеть, представление контроллеров представления было смещено соответствующим образом, чтобы его начало координат y находилось прямо под панелью навигации.
Это также может быть достигнуто программно с помощью -[UIViewController edgesForExtendedLayout]
, Вот ссылка на ссылку на класс для edgeForExtendedLayout и для UIRectEdge
[self setEdgesForExtendedLayout:UIRectEdgeNone];
Я создал свой вид программно, и это сработало для меня:
- (void) viewDidLayoutSubviews {
// only works for iOS 7+
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
CGRect viewBounds = self.view.bounds;
CGFloat topBarOffset = self.topLayoutGuide.length;
// snaps the view under the status bar (iOS 6 style)
viewBounds.origin.y = topBarOffset * -1;
// shrink the bounds of your view to compensate for the offset
viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1);
self.view.bounds = viewBounds;
}
}
Источник (в разделе topLayoutGuide внизу стр.39).
Решение Swift 3 / Swift 4, которое также работает с файлами NIB /XIB в iOS 10+:
override func viewDidLoad() {
super.viewDidLoad()
edgesForExtendedLayout = []
}
Если вы хотите, чтобы представление имело полупрозрачную навигационную панель (что довольно мило), вы должны установить contentInset или аналогичный.
Вот как я это делаю:
// Check if we are running on ios7
if([[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."][0] intValue] >= 7) {
CGRect statusBarViewRect = [[UIApplication sharedApplication] statusBarFrame];
float heightPadding = statusBarViewRect.size.height+self.navigationController.navigationBar.frame.size.height;
myContentView.contentInset = UIEdgeInsetsMake(heightPadding, 0.0, 0.0, 0.0);
}
edgesForExtendedLayout
делает то же самое для iOS 7. Однако, если вы создаете приложение в iOS 7 SDK и развертываете его в iOS 6, панель навигации выглядит полупрозрачной, и виды переходят под нее. Итак, чтобы исправить это как для iOS 7, так и для iOS 6, сделайте следующее:
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone; // iOS 7 specific
В свой plist-файл приложения добавьте строку, назовите ее "Просмотр внешнего вида строки состояния на основе контроллера" и установите для нее значение " NO".
Самый простой трюк - открыть файл NIB и выполнить эти два простых шага:
- Просто переключите это и установите тот, который вы предпочитаете:
- Выберите те UIView /UIIMageView /..., которые вы хотите переместить вниз. В моем случае только логотип был перекрыт, и я установил дельту на +15; (ИЛИ -15, если вы выбрали iOS 7 на шаге 1)
И результат:
Быстрое решение:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.edgesForExtendedLayout = UIRectEdge.None
}
Свифт 3
override func viewWillAppear(_ animated: Bool) {
self.edgesForExtendedLayout = []
}
Я хотел бы расширить ответ Stunner и добавить if
заявление, чтобы проверить, является ли это iOS-7, потому что, когда я проверял это на iOS 6, мое приложение зависало.
Дополнение будет добавлять:
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
Поэтому я бы предложил добавить этот метод в ваш MyViewControler.m
файл:
- (void) viewDidLayoutSubviews {
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
CGRect viewBounds = self.view.bounds;
CGFloat topBarOffset = self.topLayoutGuide.length;
viewBounds.origin.y = topBarOffset * -1;
self.view.bounds = viewBounds;
}
}
У меня есть сценарий, в котором я использую BannerViewController, написанный Apple для отображения моих объявлений, и ScrollViewController, встроенный в BannerViewController.
Чтобы панель навигации не скрывала мой контент, мне пришлось внести два изменения.
1) Изменить BannerViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (systemVersion >= 7.0) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
}
2) Изменить мой ScrollViewContoller
- (void)viewDidLoad
{
[super viewDidLoad];
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (systemVersion >= 7.0) {
self.edgesForExtendedLayout = UIRectEdgeBottom;
}
}
Теперь реклама правильно отображается в нижней части окна, а не закрывается панелью навигации, а содержимое вверху не обрезается.
Просто установите следующий код в поле зрения появится.
if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
Swift 4.2 - Xcode 10.0 - iOS 12.0:
if #available(iOS 11.0, *) {} else {
self.edgesForExtendedLayout = []
self.navigationController?.view.backgroundColor = .white
}
Добавьте ключ "Просмотреть внешний вид строки состояния на основе контроллера" из выпадающего списка в виде строки в info.plist
, Что-то вроде этого:
Для меня самое простое решение - добавить два ключа в список.
У меня была та же проблема с моим приложением на iPad (armv7, armv7s, amr64) только при представлении другого UIViewController, и после их отклонения появляется панель навигации под строкой состояния... Я трачу много времени, чтобы найти какое-либо решение для этого. Я использую раскадровку и в InterfaceBuilder для UIViewController, который делает ужасно, я устанавливаю презентацию из FullScreen -> Current Context, и это решает эту проблему. Это работает в моем приложении только для iPad => iOS8.0 (тестирование с iOS8.1) и для iPad с iOS 7.1 не работает!!
В моем случае прерывание loadView()
этот код:
self.edgesForExtendedLayout = UIRectEdgeNone
но после удаления loadView() все работало нормально
Шаги для скрытия строки состояния в iOS 7:
1. Перейдите в файл приложения info.plist.
2.И установить, просмотреть внешний вид строки состояния контроллера: логическое НЕТ
Надеюсь, я решил проблему со статусной строкой.....