web-dev-qa-db-fra.com

iPhone cacher 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 masqué lors du chargement de la première vue, puis masqué lorsque les "enfants" sont appelés. Le problème, c'est que je ne trouve pas l'événement/l'action qui déclenche son masquage quand ils reviennent à la vue racine.

J'ai un bouton "test" sur la page racine qui effectue l'action manuellement 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;
}
368
Lee Armstrong

La solution la plus agréable que j'ai trouvée consiste à effectuer les opérations suivantes dans le premier contrôleur de vue.

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

rapide

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)
} 

La barre de navigation s'animera à partir de la gauche (avec la vue suivante) lorsque vous placez le prochain UIViewController sur la pile, et s'éloigne à gauche (avec l'ancienne vue), lorsque vous appuyez sur le bouton de retour sur le UINavigationBar.

Notez également que ce ne sont pas des méthodes déléguées, vous redéfinissez 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.

1009
Alan Rogers

Une autre approche que j'ai trouvée consiste à définir un délégué pour la NavigationController:

navigationController.delegate = self;

et utilisez 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 au même endroit.

47
Chad M.

Un léger tweak que j'ai dû faire sur les autres réponses consiste à ne masquer la barre dans viewWillDisparear si la raison de sa disparition est due à un élément de navigation qui y est placé. En effet, la vue peut disparaître pour d'autres raisons.

Je ne montre donc 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];
}
17
user486646

Je mettrais le code dans le viewWillAppear délégué 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];
}
16
Pablo Santa Cruz

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)
}
14
Eugene Braginets

La réponse actuellement acceptée ne correspond pas au comportement prévu décrit dans la question. La question demande à ce 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 masque 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 placée dans la pile? Cela cachera la barre de navigation même si nous ne cherchons pas le contrôleur de vue racine.

Au lieu de cela, la stratégie stratégie d'utilisation de UINavigationControllerDelegate de @Chad M. est une bonne solution, et voici une solution plus complète. Pas:

  1. Sous-classe UINavigationController
  2. Implémentez la méthode -navigationController:willShowViewController:animated pour afficher ou masquer la barre de navigation en fonction de l'affichage du contrôleur de vue racine.
  3. Remplacer les méthodes d'initialisation pour définir la sous-classe UINavigationController en tant que son propre délégué

Le code complet de cette solution se trouve dans this Gist . Voici l'implémentation navigationController:willShowViewController:animated:

- (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];
    }
}
12
hunteros

Après plusieurs essais, voici comment je l’ai obtenu 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 de tabulation. Donc, je dois cacher ça aussi. - De plus, mon exigence principale n'était pas seulement de me cacher, mais aussi d'avoir un effet de disparition tout en montrant et en me 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. Je capture ce geste et le pousse dans la nouvelle imageViewController, sa dans la imageViewController, je veux 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, affichez 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 un délai (je l’ai configurée pour un délai de 1 seconde). Et après le délai, ajoutez un effet de fondu. 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 rendez le navBar 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 tout

- (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];
}
6
verma

Donnez mon crédit à la réponse de @ chad-m.

Voici la version Swift:

  1. 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)
        }
    }

}
  1. Définissez le cours de votre UINavigationController dans StoryBoard sur MyNavigationController MyNavigationController C'est tout!

Différence entre la réponse de chad-m et la mienne:

  1. Héritez de UINavigationController afin de ne pas polluer votre rootViewController.

  2. utilisez self.viewControllers.first plutôt que homeViewController, vous ne le ferez donc pas 100 fois pour vos 100 contrôleurs UINavigation dans 1 StoryBoard.

4
AI Lion

Dans le cas où quelqu'un aurait toujours des problèmes avec le bogue annulée pour le backswipe rapide comme l'a commenté @fabb 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ù navigation est masqué) et le contrôleur de vue avancée (nav est affiché) a différents styles de barre d’état (par exemple, sombre et clair). Au moment où vous lancez le balayage arrière pour faire apparaître le contrôleur de vue, il y aura une animation couleur des barres d'état supplémentaires. Si vous relâchez le doigt pour annuler le pop interactif, tant que l'animation de la barre d'état n'est pas terminée, la barre de navigation est disparue pour toujours!

Cependant, ce bogue ne se produit pas si les styles de barre d'état des deux contrôleurs de vue sont identiques.

3
aunnnn

Si vous voulez masquer complètement la barre de navigation dans le contrôleur, une solution beaucoup plus propre consiste à installer dans le contrôleur racine 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 masquée. si vous souhaitez l'afficher uniquement dans l'enfant, vous allez ajouter le code permettant d'afficher it(self.navigationController.navigationBarHidden=NO;) dans le rappel viewWillAppear, et de la même manière, le code permettant de le masquer sur viewWillDisappear

1
Alex

La mise en oeuvre la plus simple peut consister à laisser chaque contrôleur de vue 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 afficher/masquer la barre d’outils:

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setToolbarHidden:YES/NO animated:animated];
    [super viewWillAppear:animated];
}
0
SteveCaine

Masquer la barre de navigation uniquement sur la première page peut également être obtenu par le biais du storyboard. Sur le storyboard, allez scène du contrôleur de navigation-> barre de navigation. Et sélectionnez la propriété 'Caché' dans Inspecteur d'attributs. Cela masquera la barre de navigation à partir du premier contrôleur de vue jusqu'à ce qu'elle soit visible pour le contrôleur de vue requis.

La barre de navigation peut être de nouveau visible dans le rappel ViewWillAppear de ViewController.

-(void)viewWillAppear:(BOOL)animated {

    [self.navigationController setNavigationBarHidden:YES animated:animated];
    [super viewWillAppear:animated];                                                  
}
0
RSG

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)
}
0
John Riselvato