UINavigationBar/ Ошибка строки состояния в IOS7
Окончательное редактирование
(Вместо того, чтобы иметь слишком длинный вопрос с изменениями, вносящими окончательные изменения для уточнения, пожалуйста, смотрите другие изменения, если это необходимо).
Настройка контроллера
У меня есть приложение, которое настроено следующим образом:
InitialViewController (подкласс https://github.com/edgecase/ECSlidingViewController)
Главный навигационный контроллер (подкласс UINavigationController
)
Main Home View Controller (подкласс UIViewController
)
в viewDidLoad
Из начального ViewController я загружаю основной контроллер навигации с Home View Controller в качестве его корня.
self.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MainNavVC"];
Проблема
При первой загрузке приложения строка состояния и панель навигации разделяются.
Это желаемый эффект.
Однако затем я загружаю контроллер модального представления и закрываю его, используя стандартные методы:
[self performSegueWithIdentifier:@"LoadSelectOpponentVC" sender:self];
Затем закройте с помощью:
[self dismissViewControllerAnimated:YES completion:nil];
Это, в свою очередь, приводит к тому, что главный навигационный контроллер (удерживающий контроллер домашнего просмотра) отображает строку состояния неправильно и перекрывается:
тестирование
- Для параметра plist установлено значение YES -
View controller-based status bar appearance
- Я пытался установить
edgesForExtendedLayout
для соответствующих нет, но без изменений.
логирование
Я попытался выйти из некоторых кадров, чтобы увидеть, где возникает проблема:
При первой загрузке:
Main Nav VC - Просмотр кадра - {{0, 0}, {320, 480}}
Main Nav VC - Nav Bar Frame - {{0, 0}, {320, 44}}
Initial VC - View Frame - {{0, 0}, {320, 480}}
Home VC - View Frame - {{0, 0}, {320, 480}} -- viewDidLoad Home VC
Home VC - View Frame - {{0, 64}, {320, 416}} -- viewWillAppear Home VC
--- After Modal is opened/closed ----
Home VC - View Frame - {{0, 64}, {320, 416}} -- viewWillAppear Home VC
Main Nav VC - View Frame - {{0, 0}, {320, 480}} -- viewWillAppear Main Nav
Main Nav VC - Nav Bar Frame - {{0, 20}, {320, 44}} -- viewWillAppear Main Nav
Home VC - View Frame - {{0, 44}, {320, 436}} -- viewDidAppear Home VC
15 ответов
Пробовали ли вы рекомендацию Apple о том, что "не допускать, чтобы строка состояния скрывала ваши взгляды": https://developer.apple.com/library/content/qa/qa1797/_index.html
А вы взглянули на "UIBarPositionDelegate": https://developer.apple.com/documentation/uikit/uibarpositioningdelegate
В iOS 7.0 UIViewController
по умолчанию работает таким образом. Вид будет полноэкранным, если вы используете UIViewController внутри UINavigationController
и navigationBar
виден
Если навигационная панель видна, сделайте следующее. ==>
self.edgesForExtendedLayout = UIRectEdgeNone
если навигационная панель скрыта, выполните следующие действия. ==>
Отрегулируйте все UIView
элементы, сдвигая 20 очков
Если вы используете Interface Builder, вы можете использовать iOS6/7 delta: сначала "view as iOS 6.0", затем установите "20" для достижения смещения +20 в iOS 7.
Я удивлен, что никто не нашел правильный ответ. UIBarPositionDelegate работает как шарм! Просто сделайте ваш контроллер вида UIBarPositionDelegate и назначьте его в качестве делегата панели. Расположите панель в 20 пикселях от верхней части вашего обзора. Затем добавьте этот метод в свой контроллер представления (доступно только в iOS7+):
- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}
У меня была похожая проблема с кнопкой меню "гамбургер", которая сдвигала контроллер основного вида и имела контроллер представления меню сбоку. Я обнаружил, что панель навигации контроллера представления меню не знала, была ли показана строка состояния или нет. Я исправил это, опубликовав уведомление, когда строка состояния была показана и скрыта, а затем сделал
[self.navigationController setNavigationBarHidden:YES/NO animated:NO];
в контроллере вида меню.
Я исправил такую проблему, используя ответ из этого поста: iOS 7 | Кнопки панели навигации / панели инструментов расположены очень близко к строке состояния
Используя Autolayout, вы должны игнорировать установку нового кадра. Вы должны добавить ограничение Top Space, равное 20, для TopBar для iOS 7.
Вы пытались добавить следующий код к вашему viewDidLoad
метод:
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
Я знаю, что у вас есть ViewController в качестве основного VC. Но если кто-то использует UITableviewController и имеет ту же проблему, этот код решает проблему:
self.tableView.contentInset = UIEdgeInsetsMake(20.0f, 0.0f, 0.0f, 0.0f);
Я подробно ответил на эту проблему в этом ответе на аналогичный вопрос. Короткий ответ таков: нет способа получить автоматическое поведение макета строки состояния, к которому вы привыкли в iOS 6 и более ранних версиях. Вам придется придумать дизайн или найти способ имитировать старый стиль (я рассматриваю оба подхода).
Я настоятельно советую вам не вносить ручные изменения в рамку панели навигации. Пусть UINavigationController справится с этим самостоятельно. Скорее всего, ваша проблема в том, что кадр представления вашего контроллера навигации не равен границам UIScreen.
Решение этого на самом деле очень просто. Это включает в себя манипулирование UINavigationBar's center.y
значение, которое UIKit изначально использует для настройки UINavigationBar в соответствии с высотой строки состояния. Для простоты я подклассифицировал UINavigationBar и сделал следующее:
@implementation MyNavigationBar
- (void) setCenter:(CGPoint)center {
// Anything less than or equal to 22 is something we don't want (below SB height)
if(center.y > 22) [super setCenter:center];
}
@end
Да была такая же проблема. выполнил весь шаг, но без изменений.
Чтобы все заработало, убедитесь, что AutoLayout настроен правильно для всего экрана, а не только для вида сверху / панели инструментов, как указано в
"Предотвращение того, чтобы строка состояния скрывала ваши взгляды": https://developer.apple.com/library/ios/qa/qa1797/_index.html
По крайней мере, для всех видов чуть ниже основного Viewcontroller.view.
Есть встроенный способ сделать это. То же, что и ответ Джоэла Кейва, но уточняется:
Сделайте так, чтобы у вашей навигационной панели было начало координат в 20 точек.
Тогда в.h файле:
@interface XYZViewController : UIViewController <UIBarPositioningDelegate>
И в файле.m:
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationBar.delegate = self;
}
- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar {
return UIBarPositionTopAttached;
}
Я немного опоздал на вечеринку, но поскольку я столкнулся с той же проблемой, и это был первый результат, который обнаружился в поиске, я думаю, мой ответ мог бы помочь другим людям:)
Я исправил проблему, реализовав
- (BOOL)shouldAutorotate
{
return NO;
}
в контроллере представления, который представляет модал.
Попробуйте, все навигационные панели должны быть полупрозрачными - отключить.
[self.navigationController.navigationBar setTranslucent:NO];
Если вы создали свой вид с раскадровкой, то вы можете решить эту проблему с помощью XCode. Выберите виджет NavigationBar и снимите флажок "Полупрозрачный".
Лучший способ - добавить это, если у вас есть проблема с:
if (self.navigationController.navigationBar.frame.origin.y==0)
self.navigationController.navigationBar.frame =
CGRectMake(self.navigationController.navigationBar.frame.origin.x,
self.navigationController.navigationBar.frame.origin.y,
self.navigationController.navigationBar.frame.size.width,
64);