47 votes

Problème de UINavigationBar/Barre d'état dans IOS7

Final EDIT

(Plutôt que d'avoir une question trop longue avec des éditions faisant une édition finale pour clarification, veuillez voir les autres éditions si nécessaire).

Configuration du contrôleur

J'ai une application qui est configurée comme suit :

InitialViewController (sous-classe de ECSlidingViewController )

Contrôleur de navigation principal (sous-classe de UINavigationController )

Contrôleur principal de la vue d'accueil (sous-classe de UIViewController )


En el viewDidLoad du initialViewController, je charge le contrôleur de navigation principal avec le Home View Controller comme Root.

self.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MainNavVC"];

La question

Lors du premier chargement de l'application, la barre d'état et la barre de navigation sont séparées. enter image description here

C'est l'effet recherché.

Cependant, je charge ensuite un contrôleur de vue modal et le ferme, en utilisant les méthodes standard :

[self performSegueWithIdentifier:@"LoadSelectOpponentVC" sender:self];

Puis terminez par :

[self dismissViewControllerAnimated:YES completion:nil];

Cela a pour conséquence que le contrôleur de navigation principal (qui tient le contrôleur de la vue d'accueil) affiche la barre d'état de manière incorrecte et en se chevauchant :

enter image description here

Essais

  1. Le paramètre plist est réglé sur OUI - View controller-based status bar appearance
  2. J'ai essayé de régler le edgesForExtendedLayout à l'aucun pertinent, mais aucun changement.

Enregistrement

J'ai essayé de déconnecter certains cadres pour voir où le problème se produit :

Au premier chargement :

Main Nav VC - Cadre de visualisation - {{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

0 votes

"Étendre sous les barres supérieures" ne devrait affecter que la relation de votre vue avec la barre de navigation.

0 votes

Avez-vous essayé de déplacer le cadre de la barre de navigation vers le bas, de la hauteur de la barre d'état ?

0 votes

Mais où cela doit-il se faire ? Pouvez-vous fournir une réponse à cette question ?

39voto

Nicolas Buquet Points 710

Avez-vous essayé la recommandation d'Apple concernant la "Prévention de la couverture de vos vues par la barre d'état" : https://developer.apple.com/library/content/qa/qa1797/_index.html

Et avez-vous jeté un coup d'œil à "UIBarPositioningDelegate" : https://developer.apple.com/documentation/uikit/uibarpositioningdelegate

8 votes

Cette référence indique que "les applications qui utilisent un UINavigationController ou un UITabBarController opaque conservent automatiquement leur contenu sous la barre d'état", mais mon exemple et ma question montrent clairement que ce n'est pas le cas. J'ai également essayé de définir le positionnement de la barre en haut et en haut attaché, sans succès.

0 votes

J'ai utilisé la méthode décrite dans la section "Empêcher la barre d'état de couvrir vos vues", qui définit une contrainte d'espace vertical pour le guide de mise en page supérieur et la barre d'UINavigationBar que j'ai placée sur ma vue est placée sous la barre d'état. J'ai obtenu le même résultat en épinglant la UINavigationBar avec 20 pixels d'espace vertical à partir du haut de la vue.

0 votes

Assurez-vous de configurer correctement AutoLayout pour l'ensemble du viewcontroller. La documentation sur les pommes indique simplement de régler la première. J'ai seulement appliqué une contrainte entre le Guide de mise en page supérieur et la vue supérieure, et aucune autre, et cela n'a pas fonctionné. Mais cela a fonctionné une fois que j'ai ajouté des contraintes à toutes les vues en dessous de viewcontroller.view au moins et que j'ai effacé tous les avertissements de mise en page dans IB.

26voto

Sunil Adhyaru Points 384

Dans iOS 7.0 UIViewController fonctionne par défaut de cette manière. La vue sera en plein écran si vous utilisez UIViewController à l'intérieur. UINavigationController y el navigationBar est visible.

Si la barre de navigation est visible, faites ce qui suit. ==>

self.edgesForExtendedLayout = UIRectEdgeNone

si la barre de navigation est cachée, faites ce qui suit . ==>

Ajustez tous les UIView éléments en déplaçant 20 points

Si vous utilisez Interface builder, vous pouvez utiliser les deltas iOS6/7 : D'abord, "afficher comme iOS 6.0", puis définir un delta de "20" pour obtenir le décalage de +20 dans iOS 7.

0 votes

Le paramètre edgesForExtendedLayout affecte la manière dont le contrôleur d'affichage est réellement affiché avec la barre d'état, si le contenu passe en dessous, etc. J'ai indiqué dans ma question que j'avais déjà essayé cela aussi.

0 votes

@SunilAdhyaru "D'abord, "afficher comme iOS 6.0", puis définir un delta de "20" pour obtenir le décalage de +20 dans iOS 7" Pouvez-vous expliquer cela ?

0 votes

Bien sûr. En fait, vous devez définir la vue comme une iOS 6.0 au lieu de 7.0. Vous pouvez le voir dans l'élément "Document du constructeur d'interface" du constructeur d'interface.

18voto

Joel Cave Points 476

Je suis surpris que personne n'ait encore trouvé la bonne réponse. UIBarPositioningDelegate fonctionne comme un charme ! Il suffit de faire de votre contrôleur de vue un UIBarPositioningDelegate et de lui attribuer le rôle de délégué de la barre. Positionnez la barre à 20 pixels du haut de votre vue. Ajoutez ensuite cette méthode à votre contrôleur de vue (disponible uniquement dans iOS7+) :

- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar 
{ 
   return UIBarPositionTopAttached; 
}

1 votes

Non, nous avons dû adopter une approche différente en raison des contraintes de temps. Nous avons laissé la question de l'OS ouverte car toutes les réponses sont pertinentes et constituent des solutions de contournement du problème. Merci

0 votes

Pouvez-vous nous en dire plus ? A priori, vous ne pouvez pas définir le délégué d'une barre de navigation lorsqu'elle est gérée par un contrôleur de navigation.

4 votes

Cette solution fonctionne lorsqu'on ajoute une barre de navigation personnalisée à un UIViewController. Pour un UINavigationController, vous devrez créer une sous-classe de UINavigationController et définir cette sous-classe comme un UINavigationBarDelegate (qui est conforme à UIBarPositioningDelegate), comme ceci : stackoverflow.com/a/7453933/485895 . Il suffit d'ajouter la méthode positionForBar : mentionnée dans ma réponse pour résoudre le problème en question, mais vous pouvez voir que cette approche par sous-classe vous offre également d'autres possibilités.

4voto

Stephen Johnson Points 812

J'ai eu un problème similaire avec un bouton de menu "hamburger" qui faisait glisser le contrôleur de vue principal et avait un contrôleur de vue de menu sur le côté. J'ai découvert que la barre de navigation du contrôleur de vue du menu ne savait pas si la barre d'état était affichée ou non. J'ai corrigé le problème en affichant une notification lorsque la barre d'état était affichée ou masquée, puis en faisant ce qui suit

[self.navigationController setNavigationBarHidden:YES/NO animated:NO];

dans le contrôleur de vue du menu.

3voto

grigorievs Points 82

J'ai résolu un tel problème en utilisant la réponse de ce post : iOS 7 | Barre de navigation / boutons de la barre d'outils très proches de la barre d'état

En utilisant Autolayout, vous devez ignorer la définition d'un nouveau cadre. Vous devez ajouter une contrainte d'espace supérieur égale à 20 pour la barre supérieure d'iOS 7.

0 votes

J'ai essayé la résolution de cette question, mais sans succès. Pouvez-vous fournir un exemple de code de la façon dont vous avez configuré l'AutoLayout, ou avez-vous concouru dans IB ?

0 votes

1. Ajoutez une sortie pour la contrainte d'espace de la barre supérieure (Espace vertical - Barre de navigation - Vue) dans le code. 2. Définissez le délégué de la barre d'outils au VC correspondant. 3. Ajouter la méthode de delegate comme spécifié dans l'url ci-dessus. 4. Ajouter cette méthode dans viewWillAppear > if (IS_IOS_7) self.navBarTopSpaceConstraint.constant = 20 ;

0 votes

Je n'ai pas encore été en mesure de tester cela, je vais bientôt le faire et mettre à jour.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X