it-swarm.com.ru

Как правильно установить высоту UINavigationBar в iOS 11

В моем приложении для iOS 9+ я использую UINavigationBar в некоторых из UIViewControllers «вручную» (= помещая их непосредственно в VC вместо использования UINavigationViewController).

Задание высоты для такой UINavigationBar с использованием простого противопоказания раньше не было проблемой. Однако в iOS 11 сама панель по-прежнему правильно использует назначенный размер, но контент больше не позиционируется правильно (теперь выровнен по верху). 

 enter image description here

Есть идеи, как это решить?

Правка:

Я уверен, что это не дубликат " настройка высоты панели навигации iOS 11 ", этот вопрос решает проблему с подклассами UINavigationBar, в то время как я непосредственно использую UINavigationBar. Кроме того, описанная проблема, кажется, решена начиная с бета-версии 4, в то время как я испытываю проблему в бета-версии 6.

Правка 2:

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

4
Andrei Herford

Я сталкиваюсь с этой проблемой прямо сейчас ... Во-первых, это похоже на другое ограничение высоты в баре, которое конфликтует с моим, но у моего приоритета 1000, так что, похоже, проблема не в этом. Затем я вижу другой вид внутри UINavigationBar "UINavigationBarContentView", этот вид имеет высоту больше 0.

Затем я попытался установить navigationBar.clipsToBounds = true, и это работает, потому что родительский вид имеет правильную высоту ... 

Правка: Если вам нужно показать тень от панели, вам понадобится clipToBounds = false. В этом случае вы можете создать подкласс NavigationBar 

import UIKit

class SecondNavigationBar: UINavigationBar {
    override func layoutSubviews() {
        super.layoutSubviews()

        for subview in self.subviews {
            var stringFromClass = NSStringFromClass(subview.classForCoder)
            print("--------- \(stringFromClass)")
            if stringFromClass.contains("BarBackground") {
                subview.frame = self.bounds
            } else if stringFromClass.contains("UINavigationBarContentView") {
                subview.frame = self.bounds
            }
        }
    }
}
2
Eva Madrazo

У меня тоже была эта проблема. Я решил это так:

 -(void)layoutSubviews{
        [super layoutSubviews];
        CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame];
        if (rectStatus.size.height==44.f) {

        }else{
            if (@available(iOS 11.0, *)) {
                for ( UIView*aView in self.subviews) {
                    if ([NSStringFromClass(aView.classForCoder) isEqualToString:@"_UINavigationBarContentView"]) {
                        aView.frame = CGRectMake( 0,20,aView.frame.size.width,44);
                    }
                    else if ([NSStringFromClass(aView.classForCoder) isEqualToString:@"_UIBarBackground"]) {
                        aView.frame = CGRectMake(0,0,aView.frame.size.width, 64);
                    }
                }
            }
        }
    }
2
user8639894

В iOS 11 мы можем напрямую переопределить barPosition в подклассе UINavigationBar (вместо UIBarPositionTopAttached вместо значения по умолчанию UIBarPositionTop), когда вы используете пользовательский UINavigationBar в UIViewController
как это :

- (UIBarPosition)barPosition {
    return UIBarPositionTopAttached;
}

код макета будет выглядеть так:

    NSLayoutConstraint* a = [navigationBar.widthAnchor constraintEqualToAnchor:viewController.view.widthAnchor];
    NSLayoutConstraint *b = [navigationBar.centerXAnchor constraintEqualToAnchor:viewController.view.centerXAnchor constant:0];
    NSLayoutConstraint* c = [navigationBar.centerYAnchor constraintEqualToAnchor:viewController.view.topAnchor constant:X];

   [NSLayoutConstraint activateConstraints:@[a,b,c]];   

Не устанавливайте его высоту, оно всегда должно быть 44. 

Это хорошо работает в iOS 11. Иерархия представлений такая же, как в UINavigationController.
Но это не работает ниже iOS 11. Нам нужно установить UINavigationBarDelegate для возврата UIBarPositionTopAttached в 

- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar;  
0
PatrickChow