iPhone masquer la barre de Navigation uniquement sur la première page
J'ai le code ci-dessous qui cache et montre la barre de navigation. Il est caché lorsque la première vue se charge, puis caché lorsque les "enfants" sont appelés. Le problème est que je ne peux pas trouver l'événement / action pour le déclencher pour se cacher à nouveau quand ils reviennent à la vue racine....
J'ai un bouton "test" sur la page racine qui fait manuellement l'action mais ce n'est pas joli et je veux que ce soit automatique.
-(void)hideBar
{
self.navController.navigationBarHidden = YES;
}
-(void)showBar
{
self.navController.navigationBarHidden = NO;
}
14 réponses
La plus belle solution que j'ai trouvé est de faire ce qui suit dans le première vue-contrôleur.
Objectif-C
- (void)viewWillAppear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:YES animated:animated];
[super viewWillAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:NO animated:animated];
[super viewWillDisappear:animated];
}
Swift
override func viewWillAppear(animated: Bool) {
self.navigationController?.setNavigationBarHidden(true, animated: animated)
super.viewWillAppear(animated)
}
override func viewWillDisappear(animated: Bool) {
self.navigationController?.setNavigationBarHidden(false, animated: animated)
super.viewWillDisappear(animated)
}
Cela entraînera l'animation de la barre de navigation depuis la gauche (avec la vue suivante) lorsque vous poussez le UIViewController
suivant sur la pile, et l'animation vers la gauche (avec l'ancienne vue), lorsque vous appuyez sur le bouton Précédent sur le UINavigationBar
.
Veuillez noter également que ce ne sont pas des méthodes déléguées, vous sont remplaçant l'implémentation de UIViewController
de ces méthodes, et selon la documentation, Vous devez appeler l'implémentation du super quelque part dans votre implémentation.
Une autre approche que j'ai trouvée est de définir un délégué pour le NavigationController
:
navigationController.delegate = self;
Et utiliser setNavigationBarHidden
dans navigationController:willShowViewController:animated:
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
// Hide the nav bar if going home.
BOOL hide = viewController != homeViewController;
[navigationController setNavigationBarHidden:hide animated:animated];
}
Un moyen facile de personnaliser le comportement de chaque ViewController
en un seul endroit.
Je mettrais le code dans le délégué viewWillAppear sur chaque vue affichée:
Comme ceci où vous devez le cacher:
- (void)viewWillAppear:(BOOL)animated
{
[yourObject hideBar];
}
Comme ceci où vous devez le montrer:
- (void)viewWillAppear:(BOOL)animated
{
[yourObject showBar];
}
Un léger tweak que j'ai dû faire sur les autres réponses est de ne montrer la barre dans viewWillDisappear que si la raison pour laquelle elle disparaît est due à un élément de navigation poussé dessus. C'est parce que la vue peut disparaître pour d'autres raisons.
Donc, je n'affiche la barre que si cette vue n'est plus la vue la plus haute:
- (void) viewWillDisappear:(BOOL)animated
{
if (self.navigationController.topViewController != self)
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
[super viewWillDisappear:animated];
}
Dans Swift 3:
override func viewWillAppear(_ animated: Bool) {
navigationController?.navigationBar.isHidden = true
super.viewWillAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
if (navigationController?.topViewController != self) {
navigationController?.navigationBar.isHidden = false
}
super.viewWillDisappear(animated)
}
La réponse actuellement acceptée ne correspond pas au comportement prévu décrit dans la question. La question demande que la barre de navigation soit masquée sur le contrôleur de vue racine, mais visible partout ailleurs, mais la réponse acceptée cache la barre de navigation sur un contrôleur de vue particulier. Que se passe-t-il lorsqu'une autre instance du premier contrôleur de vue est poussée sur la pile? Il masquera la barre de navigation même si nous ne regardons pas le contrôleur de vue racine.
À la place, La stratégie de @ Chad M. d'utilisation du UINavigationControllerDelegate
est bonne, et voici une solution plus complète. Étapes:
- sous-classe
UINavigationController
- implémentez la méthode
-navigationController:willShowViewController:animated
pour afficher ou masquer la barre de navigation selon qu'elle affiche le contrôleur de vue racine - remplace les méthodes d'initialisation pour définir la sous-classe UINavigationController comme son propre délégué
Le code complet de cette solution peut être trouvé dans cet essentiel . Voici le navigationController:willShowViewController:animated
mise en œuvre:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
/* Hide navigation bar if root controller */
if ([viewController isEqual:[self.viewControllers firstObject]]) {
[self setNavigationBarHidden:YES animated:animated];
} else {
[self setNavigationBarHidden:NO animated:animated];
}
}
Après plusieurs essais, voici comment je l'ai fait fonctionner pour ce que je voulais. C'est ce que j'essayais. - J'ai une vue avec une image. et je voulais que l'image passe en plein écran. - J'ai aussi un contrôleur de navigation avec une barre d'onglets. J'ai donc besoin de cacher que, trop. - En outre, ma principale exigence n'était pas seulement de se cacher, mais d'avoir un effet de décoloration aussi tout en montrant et en se cachant.
C'est comme ça que je l'ai fait fonctionner.
Étape 1-j'ai une image et l'utilisateur tape sur cette image Une fois. J'ai fait une capture ce geste et le pousser dans le nouveau imageViewController
, à imageViewController
, je veux avoir une image en plein écran.
- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer {
NSLog(@"Single tap");
ImageViewController *imageViewController =
[[ImageViewController alloc] initWithNibName:@"ImageViewController" bundle:nil];
godImageViewController.imgName = // pass the image.
godImageViewController.hidesBottomBarWhenPushed=YES;// This is important to note.
[self.navigationController pushViewController:godImageViewController animated:YES];
// If I remove the line below, then I get this error. [CALayer retain]: message sent to deallocated instance .
// [godImageViewController release];
}
Étape 2-Toutes ces étapes ci-dessous sont dans ImageViewController
Étape 2.1 - dans ViewDidLoad, afficher la barre de navigation
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(@"viewDidLoad");
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}
Étape 2.2-dans viewDidAppear
, configurez une tâche de minuterie avec retard ( je l'ai définie pour un délai de 1 seconde). Et après le retard, ajouter l'effet de décoloration. J'utilise alpha pour utiliser la décoloration.
- (void)viewDidAppear:(BOOL)animated
{
NSLog(@"viewDidAppear");
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(fadeScreen) userInfo:nil repeats:NO];
}
- (void)fadeScreen
{
[UIView beginAnimations:nil context:nil]; // begins animation block
[UIView setAnimationDuration:1.95]; // sets animation duration
self.navigationController.navigationBar.alpha = 0.0; // Fades the alpha channel of this view to "0.0" over the animationDuration of "0.75" seconds
[UIView commitAnimations]; // commits the animation block. This Block is done.
}
Étape 2.3-sous viewWillAppear
, ajoutez un geste singleTap à l'image et rendre la barre de navigation translucide.
- (void) viewWillAppear:(BOOL)animated
{
NSLog(@"viewWillAppear");
NSString *path = [[NSBundle mainBundle] pathForResource:self.imgName ofType:@"png"];
UIImage *theImage = [UIImage imageWithContentsOfFile:path];
self.imgView.image = theImage;
// add tap gestures
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[self.imgView addGestureRecognizer:singleTap];
[singleTap release];
// to make the image go full screen
self.navigationController.navigationBar.translucent=YES;
}
- (void)handleTap:(UIGestureRecognizer *)gestureRecognizer
{
NSLog(@"Handle Single tap");
[self finishedFading];
// fade again. You can choose to skip this can add a bool, if you want to fade again when user taps again.
myTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(fadeScreen) userInfo:nil repeats:NO];
}
Étape 3-Enfin dans viewWillDisappear
, assurez-vous de remettre toutes les choses
- (void)viewWillDisappear: (BOOL)animated
{
self.hidesBottomBarWhenPushed = NO;
self.navigationController.navigationBar.translucent=NO;
if (self.navigationController.topViewController != self)
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
[super viewWillDisappear:animated];
}
Au cas où quelqu'un aurait encore des problèmes avec le bogue Fast backswipe annulé comme @fabb a commenté dans la réponse acceptée.
Je parviens à résoudre ce problème en remplaçant viewDidLayoutSubviews
, en plus de viewWillAppear/viewWillDisappear
comme indiqué ci-dessous:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
//*** This is required to fix navigation bar forever disappear on fast backswipe bug.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.navigationController?.setNavigationBarHidden(false, animated: false)
}
Dans mon cas, je remarque que c'est parce que le contrôleur de vue racine (où nav est caché) et le contrôleur de vue poussé (nav est affiché) ont des styles de barre d'État différents (par exemple sombre et clair). Au moment où vous démarrez le backswipe pour faire apparaître la vue contrôleur, il y aura l'animation supplémentaire de couleur de barre d'état. Si vous relâchez votre doigt pour annuler la pop interactive, alors que l'animation de la barre d'état n'est pas terminée , la barre de navigation est définitivement disparue!
Cependant, ce bogue ne se produit pas si les styles de barre d'état des deux contrôleurs de vue sont les mêmes.
Si ce que vous voulez est de masquer complètement la barre de navigation dans le contrôleur, une solution beaucoup plus propre est, dans le contrôleur racine, d'avoir quelque chose comme:
@implementation MainViewController
- (void)viewDidLoad {
self.navigationController.navigationBarHidden=YES;
//...extra code on view load
}
Lorsque vous appuyez sur une vue enfant dans le contrôleur, la barre de Navigation reste cachée; si vous voulez l'afficher uniquement dans l'enfant, vous ajoutez le code pour afficher it(self.navigationController.navigationBarHidden=NO;)
dans le rappel viewWillAppear
, et de même le code pour le cacher sur viewWillDisappear
Donnez mon crédit à la réponse de @chad-m.
Voici la version Swift:
- Créer un nouveau fichier
MyNavigationController.swift
import UIKit
class MyNavigationController: UINavigationController, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.delegate = self
}
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
if viewController == self.viewControllers.first {
self.setNavigationBarHidden(true, animated: animated)
} else {
self.setNavigationBarHidden(false, animated: animated)
}
}
}
- définissez la classe de votre UINavigationController dans StoryBoard sur MyNavigationController C'est ça!
Différence entre la réponse de chad-m et la mienne:
Hériter de UINavigationController, de sorte que vous ne polluerez pas votre rootViewController.
Utiliser
self.viewControllers.first
plutôt quehomeViewController
, donc vous ne le ferez pas 100 fois pour vos 100 UINavigationControllers dans 1 StoryBoard.
L'implémentation la plus simple peut être de simplement demander à chaque contrôleur de vue de spécifier si sa barre de navigation est masquée ou non dans sa méthode viewWillAppear:animated:
. La même approche fonctionne bien pour masquer/afficher la barre d'outils:
- (void)viewWillAppear:(BOOL)animated {
[self.navigationController setToolbarHidden:YES/NO animated:animated];
[super viewWillAppear:animated];
}
Masquer la barre de navigation uniquement sur la première page peut également être réalisé via storyboard. Sur storyboard, goto scène du contrôleur de Navigation- > barre de Navigation . Et sélectionnez 'Caché " propriété de la Attributs de l'inspecteur de. Cela masquera la barre de navigation à partir du premier viewcontroller jusqu'à ce qu'elle soit visible pour le viewcontroller requis.
La barre de Navigation peut être définie sur visible dans le rappel ViewWillAppear de ViewController.
-(void)viewWillAppear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:YES animated:animated];
[super viewWillAppear:animated];
}
Swift 4:
Dans le contrôleur de vue, vous souhaitez masquer la barre de navigation.
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(true, animated: animated)
super.viewWillAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(false, animated: animated)
super.viewWillDisappear(animated)
}
En implémentant ce code dans votre ViewController, vous pouvez obtenir cet effet En fait, l'astuce est de masquer la barre de navigation lorsque ce contrôleur est lancé
- (void)viewWillAppear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:YES animated:YES];
[super viewWillAppear:animated];
}
Et affichez la barre de navigation lorsque l'utilisateur quitte cette page, faites ceci est viewWillDisappear
- (void)viewWillDisappear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:NO animated:YES];
[super viewWillDisappear:animated];
}