iPhone nasconde la barra di navigazione solo nella prima pagina


382

Ho il codice sotto che nasconde e mostra la barra di navigazione. È nascosto quando viene caricata la prima vista e quindi nascosto quando vengono chiamati i "figli". Il problema è che non riesco a trovare l'evento / azione per attivarlo per nasconderlo di nuovo quando tornano alla vista principale ....

Ho un pulsante "test" sulla pagina principale che esegue manualmente l'azione ma non è carino e voglio che sia automatico.

-(void)hideBar 
{
    self.navController.navigationBarHidden = YES;
}
-(void)showBar 
{       
    self.navController.navigationBarHidden = NO;
}

Risposte:


1035

La soluzione più bella che ho trovato è quella di fare quanto segue nel controller della prima vista .

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

veloce

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

Questo farà sì che la barra di navigazione si animi da sinistra (insieme alla vista successiva) quando si preme il successivo UIViewControllersullo stack e si animerà a sinistra (insieme alla vista precedente), quando si preme il pulsante Indietro sul UINavigationBar.

Si noti inoltre che questi non sono metodi delegati, si sta sovrascrivendo UIViewControllerl'implementazione di questi metodi e, secondo la documentazione, è necessario chiamare l'implementazione del super da qualche parte nella propria implementazione .


2
Questo è assolutamente incredibile! Ho lottato con questo per almeno un giorno. Grazie!!!
James Testa,

26
ATTENZIONE: questo crea un bug molto grave quando si esegue una backswipe veloce. Supponiamo che A (nessuna barra di navigazione) e B (con barra di navigazione) siano stati inseriti nella pila. Quando viene visualizzato B e si esegue un backswipe veloce, ma rilascialo abbastanza presto per rimanere su B, la barra di navigazione viene comunque nascosta. Ora non c'è più modo di tornare indietro. Ciò è dovuto a animated=YES. So che sembra brutto animated=NO, ma sembra che quando l'animazione per nascondere la barra di navigazione non è ancora finita, l'animazione per mostrarla di nuovo viene ignorata. Nessuna soluzione ancora.
fabb

3
In Swift: override func viewWillAppear (animato: Bool) {self.navigationController? .SetNavigationBarHidden (true, animato: true) super.viewWillAppear (true)} override func viewWillDisappear (animato: Bool) {self.navigationController? .SetNavigationBarHidden (false, animato: falso) super.viewWillDisappear (true)}
Kitson,

7
Alla domanda è stata data risposta nel 2010 e mi aiuta a fine 2015! Grazie.
Oyalhi,

1
Questo è quello che chiamo una risposta leggendaria. Superbo compagno di trucco. Anche dopo decenni di lavoro ... Implementato lo stesso in modo rapido e senza problemi. +1 per la tua risposta @Alan Rogers
onCompletion

62

Un altro approccio che ho trovato è quello di impostare un delegato per NavigationController:

navigationController.delegate = self;

e utilizzare setNavigationBarHiddeninnavigationController: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];
}

Modo semplice per personalizzare il comportamento per ognuno ViewControllerin un unico posto.


Quando verrà chiamato?
Zalak Patel,

1
Soluzione perfetta Questa dovrebbe essere la risposta accettata. Grazie!
Samah,

Risposta perfetta Funziona anche nel caso in cui non possiamo ignorare i metodi viewWillAppear e viewWillDisappear sul controller della prima vista.
pjuzeliunas,

1
Eccezionale. La risposta scelta funziona bene, tuttavia solo nelle app semplici. Questa risposta funziona quando la barra di navigazione si trova in un controller di scheda e spinge / presenta vari VC in vari modi.
Jonathan Winger-Lang,

Questa è la risposta migliore La risposta migliore può verificarsi un bug come descrizione di @ fabb .
Ryan.Yuen,

19

Un leggero accorgimento che ho dovuto fare sulle altre risposte è quello di scoprire la barra in vista. Scompare se il motivo per cui sta scomparendo è dovuto alla spinta di un elemento di navigazione su di essa. Questo perché la vista può scomparire per altri motivi.

Quindi scopro la barra solo se questa vista non è più la vista più in alto:

- (void) viewWillDisappear:(BOOL)animated
{
    if (self.navigationController.topViewController != self)
    {
        [self.navigationController setNavigationBarHidden:NO animated:animated];
    }

    [super viewWillDisappear:animated];
}

3
+1, di solito non si desidera mostrare la barra di navigazione quando si preme una finestra di dialogo modale.
João Portela,

17

Vorrei mettere il codice nel delegato viewWillAppear su ciascuna vista mostrata:

In questo modo è necessario nasconderlo:

- (void)viewWillAppear:(BOOL)animated
{
        [yourObject hideBar];
}

In questo modo è necessario mostrarlo:

- (void)viewWillAppear:(BOOL)animated
{
        [yourObject showBar];
}

Lee, se questo ha risolto il tuo problema, segna quella di Pablo come la "soluzione".
Rog,

2
L'unico problema è che la barra di navigazione "si apre" e diventa visibile mentre navighi da una vista all'altra. È possibile solo avere la barra di navigazione non presente nella prima vista e quando la seconda vista si sposta in posizione, ha la barra di navigazione, senza fare scoppiare?
Henning,

2
@henning Per far entrare / uscire la NavBar come ci si aspetterebbe, è necessario utilizzare setNavigationBarHidden: animato :. Vedi la risposta di Alan Rogers di seguito (che dovrebbe essere contrassegnata come "soluzione").
Nick Forge,

2
Questa risposta è leggermente sbagliata (viewWill / DidAppear) dovrebbe chiamare super. Vedi anche la mia risposta di seguito per una soluzione in cui non è necessario aggiungerla a OGNI controller di visualizzazione.
Alan Rogers

15

La risposta attualmente accettata non corrisponde al comportamento previsto descritto nella domanda. La domanda richiede che la barra di navigazione sia nascosta sul controller della vista radice, ma sia visibile ovunque, ma la risposta accettata nasconde la barra di navigazione su un particolare controller della vista. Cosa succede quando un'altra istanza del controller della prima vista viene inserita nello stack? Nasconderà la barra di navigazione anche se non stiamo osservando il controller della vista principale.

Invece, la strategia di @Chad M. di usare il UINavigationControllerDelegateè una buona, ed ecco una soluzione più completa. passi:

  1. sottoclasse UINavigationController
  2. Implementare il -navigationController:willShowViewController:animated metodo per mostrare o nascondere la barra di navigazione in base alla visualizzazione del controller della vista principale
  3. Sostituire i metodi di inizializzazione per impostare la sottoclasse UINavigationController come proprio delegato

Il codice completo per questa soluzione è disponibile in questo Gist . Ecco l' navigationController:willShowViewController:animatedimplementazione:

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

2
Questa è una risposta più appropriata di quella accettata
Pavel Gurov il

14

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

potresti spiegare perché controlli! = self?
Kitson,

2
@Kitson, controlla la risposta dell'utente486646: Un leggero accorgimento che ho dovuto fare sulle altre risposte è quello di scoprire la barra in vista. Scompare se il motivo che sta scomparendo è dovuto al fatto che un elemento di navigazione è stato spinto su di essa. Questo perché la vista può scomparire per altri motivi. Quindi scopro il bar solo se questa vista non è più la vista più in alto
Eugene Braginets,

Sembra che se lo usi navcontroller.navagationBarHiddensi romperà l'intero controller di navigazione (senza scorrere avanti e indietro). Per farlo funzionare ho usato navigationController?.navigationBar.hiddeninvece. Lo scorrimento funziona ancora e non lascia spazio vuoto perché sembra essere all'interno di uno stackview o qualcosa del genere
Sirene

8

Dai il mio credito alla risposta di @ chad-m.

Ecco la versione Swift:

  1. Crea un nuovo file 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. Imposta la classe del tuo UINavigationController in StoryBoard su MyNavigationController Questo è tutto!MyNavigationController

Differenza tra la risposta di chad-m e la mia:

  1. Eredita da UINavigationController, quindi non inquinerai rootViewController.

  2. usare self.viewControllers.firstinvece di homeViewController, quindi non lo farai 100 volte per i tuoi 100 UINavigationController in 1 StoryBoard.


Pensa che questa sia la risposta più pulita. Grazie
DaSilva

6

Dopo più prove, ecco come l'ho fatto funzionare per quello che volevo. Questo è quello che stavo provando. - Ho una vista con un'immagine. e volevo che l'immagine fosse a schermo intero. - Ho anche un controller di navigazione con una tabBar. Quindi devo nascondere anche quello. - Inoltre, il mio requisito principale non era solo nascondermi, ma anche avere un effetto sbiadito mentre mostravo e nascondevo.

Ecco come l'ho fatto funzionare.

Passaggio 1: ho un'immagine e l'utente tocca quell'immagine una volta. Catturo quel gesto e lo spingo nel nuovo imageViewController, è nel imageViewController, voglio avere un'immagine a schermo intero.

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

Passaggio 2: tutti i passaggi seguenti si trovano in ImageViewController

Passaggio 2.1 - In ViewDidLoad, mostra la barra di navigazione

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(@"viewDidLoad");
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}

Passaggio 2.2 - In viewDidAppear, impostare un'attività timer con ritardo (l'ho impostato per 1 secondo di ritardo). E dopo il ritardo, aggiungi l'effetto di dissolvenza. Sto usando l'alfa per usare la dissolvenza.

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

step 2.3 - Sotto viewWillAppear, aggiungi il gesto singleTap all'immagine e rendi la navBar traslucida.

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

Passaggio 3: Infine viewWillDisappear, assicurati di rimettere tutto il materiale

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

4

Nel caso in cui qualcuno abbia ancora problemi con il bug cancellato backswipe veloce come commentato da @fabb nella risposta accettata.

Riesco a risolvere questo problema ignorando viewDidLayoutSubviews, oltre a viewWillAppear/viewWillDisappearcome mostrato di seguito:

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

Nel mio caso, noto che ciò è dovuto al fatto che il controller della vista principale (dove è nascosto il navigatore) e il controller della vista spinta (viene mostrato il navigatore) ha stili di barra di stato diversi (ad es. Scuro e chiaro). Nel momento in cui avvii il backswipe per far apparire il controller di visualizzazione, ci sarà un'ulteriore animazione del colore della barra di stato. Se rilasci il dito per annullare il pop interattivo, mentre l'animazione della barra di stato non è terminata , la barra di navigazione è sparita per sempre!

Tuttavia, questo errore non si verifica se gli stili della barra di stato di entrambi i controller di visualizzazione sono gli stessi.


1

Se quello che vuoi è nascondere completamente la barra di navigazione nel controller, una soluzione molto più pulita è, nel controller di root, avere qualcosa del tipo:

@implementation MainViewController
- (void)viewDidLoad {
    self.navigationController.navigationBarHidden=YES;
    //...extra code on view load  
}

Quando si preme una vista figlio nel controller, la barra di navigazione rimarrà nascosta; se si desidera visualizzarlo solo nel figlio, aggiungere il codice per la visualizzazione it(self.navigationController.navigationBarHidden=NO;)nel viewWillAppearcallback e allo stesso modo il codice per nasconderloviewWillDisappear


0

L'implementazione più semplice potrebbe essere quella di far specificare a ciascun controller di visualizzazione se la sua barra di navigazione è nascosta o meno nel suo viewWillAppear:animated:metodo. Lo stesso approccio funziona bene anche per nascondere / mostrare la barra degli strumenti:

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

In realtà, il mio suggerimento ha senso solo per la barra degli strumenti, poiché nascondere la barra di navigazione senza una chiamata corrispondente per mostrare che non consentirebbe agli utenti di tornare indietro dalla vista corrente.
SteveCaine,

0

È possibile nascondere la barra di navigazione solo nella prima pagina tramite lo storyboard. Nello storyboard, vai alla scena del controller di navigazione-> barra di navigazione . E seleziona la proprietà ' Nascosto ' dalla finestra di ispezione Attributi . Ciò nasconderà la barra di navigazione a partire dal primo viewcontroller fino a renderlo visibile per il viewcontroller richiesto.

La barra di navigazione può essere ripristinata per essere visibile nel callback ViewWillAppear di ViewController.

-(void)viewWillAppear:(BOOL)animated {

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

0

Swift 4:

Nel controller di visualizzazione si desidera nascondere la barra di navigazione.

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

-1

Implementando questo codice nel ViewController puoi ottenere questo effetto In realtà il trucco è, nascondere la barra di navigazione all'avvio di quel Controller

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:YES animated:YES];
    [super viewWillAppear:animated];
}

e scopri la barra di navigazione quando l'utente lascia quella pagina per fare ciò è viewWillDisappear

- (void)viewWillDisappear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:NO animated:YES];
    [super viewWillDisappear:animated];
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.