web-dev-qa-db-fra.com

Comment définir correctement la hauteur de UINavigationBar dans iOS 11

Dans mon application iOS 9+, j'utilise UINavigationBardans certains des UIViewControllername__s "manuellement" (= en les plaçant directement dans le VC au lieu d'utiliser UINavigationViewControllername__).

Définir une hauteur pour une telle UINavigationBaren utilisant une simple contrainte n’était pas un problème auparavant. Cependant, dans iOS 11, la barre elle-même utilise toujours correctement la taille attribuée, mais le contenu n'est plus correctement positionné (il est maintenant alloué en haut). 

enter image description here

Une idée comment résoudre ce problème?

MODIFIER:

Je suis presque certain qu'il ne s'agit pas d'un doublon de " personnalisation de la hauteur de la barre de navigation iOS 11 }", cette question répond à un problème avec les sous-classes UINavigationBaralors que j'utilise directement UINavigationBarname__. De plus, le problème décrit semble résolu depuis la version 4, alors que je suis confronté au problème en version 6.

EDIT 2:

En attendant, j'ai implémenté une sous-classe UINavigationBarcomme proposé par CharlieSu dans l'autre thread . Cependant, cela n'a pas résolu le problème dans mon cas. Il semble que les cadres de sous-vue soient tous correctement définis (sans le faire manuellement), mais la présentation est quand même brisée. Donc, le réglage manuel des images ne fait aucune différence. 

4
Andrei Herford

Je fais face à ce problème actuellement. Au début, il semble que le bar soit une autre contrainte de hauteur qui entre en conflit avec le mien, mais le mien a une priorité de 1000, ce qui ne semble pas être le problème. Puis, je vois une autre vue à l'intérieur de UINavigationBar "UINavigationBarContentView", cette vue a une hauteur supérieure à 0.

J'ai ensuite essayé de définir navigationBar.clipsToBounds = true et cela fonctionne car la vue parent a la bonne hauteur ... 

EDIT: Si vous devez afficher l'ombre de la barre, vous aurez besoin de clipToBounds = false. Dans ce cas, vous pouvez sous-classer le 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

J'ai eu ce problème aussi. Je l'ai résolu de cette façon:

 -(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

Dans iOS 11, nous pouvons directement remplacer barPosition dans la sous-classe de UINavigationBar (renvoyer UIBarPositionTopAttached à la place de la valeur par défaut UIBarPositionTop) lorsque vous utilisez UINavigationBar personnalisé dans UIViewController
comme ça :

- (UIBarPosition)barPosition {
    return UIBarPositionTopAttached;
}

le code de mise en page sera comme ceci:

    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]];   

Ne réglez pas sa hauteur, elle devrait toujours être 44. 

Cela fonctionne bien dans iOS 11. La hiérarchie des vues est identique à celle de UINavigationController.
Mais cela ne fonctionne pas sous iOS 11. Nous devons définir UINavigationBarDelegate pour renvoyer UIBarPositionTopAttached dans 

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