В iOS 7, если я скрываю строку состояния с помощью метода `prefersStatusBarHidden`, навигационная панель сжимается/теряет высоту. Могу ли я остановить это поведение?

В iOS 7, если я использую метод prefersStatusBarHidden и возвращаю переменную экземпляра, которую можно изменить:

- (BOOL)prefersStatusBarHidden {
    return self.statusBarShouldBeHidden;
}

И я изменяю переменную экземпляра, тем самым скрывая строку состояния, панель навигации теряет 20pt высоты, которую занимает строка состояния. Однако я не хочу этого. Можно ли скрыть строку состояния, но сохранить высоту панели навигации?

Ответ 1

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

Я сделал это так, как раньше (heightCon - это IBOutlet для ограничения высоты на панели навигации).

-(IBAction)hideStatusBar:(id)sender {
    static BOOL hidden = YES;
    [[UIApplication sharedApplication] setStatusBarHidden:hidden withAnimation:UIStatusBarAnimationSlide];
    self.heightCon.constant = (hidden)? 64 : 44;
    [UIView animateWithDuration:0.35 animations:^{
        [self.navBar layoutIfNeeded];
    }];
    hidden = ! hidden;
}

Ответ 2

Я нашел одно решение этой проблемы на следующем блоге: http://www.factorialcomplexity.com/blog/2014/08/05/fixed-height-navigation-bar-on-ios7.html, но его решение использует метод swizzling на UINavigationBar, который я нахожу непривлекательным.

UPDATE:

Я понял, что подклассификация UINavigationBar и предоставление подобной реализации swizzled решению решает эту проблему (Swift здесь, но то же самое работает в Obj-C):

class MyNavigationBar: UINavigationBar {
    override func sizeThatFits(size: CGSize) -> CGSize {
        var size = super.sizeThatFits(size)
        if UIApplication.sharedApplication().statusBarHidden {
            size.height = 64
        }
        return size
    }
}

Затем обновите класс панели навигации в своем раскадровке или используйте initWithNavigationBarClass:toolbarClass: при создании контроллера навигации для использования нового класса.

Ответ 3

Я не получил решение @rdelmar для работы с NSLayoutConstraint, но я использовал его идею, чтобы придумать этот очень простой код.

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
[UIView animateWithDuration:0.35
                      delay:0
                    options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^{
                             self.navigationBar.top = 20;
                 }
                 completion:nil];

options:UIViewAnimationOptionBeginFromCurrentState очень важен, иначе анимация отрывается, потому что она начинается с 0.