Domanda

Ho il codice sotto che nasconde e mostra la barra di navigazione. Viene nascosto quando viene caricata la prima vista e quindi nascosto quando & Quot; children & Quot; essere chiamato. Il problema è che non riesco a trovare l'evento / azione per attivarlo per nasconderlo di nuovo quando tornano alla vista principale ....

Ho un " test " pulsante 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;
}
È stato utile?

Soluzione

La soluzione più bella che ho trovato è quella di eseguire le seguenti operazioni nel controller di prima visualizzazione .

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

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

Questo farà animare la barra di navigazione da sinistra (insieme alla vista successiva) quando si spinge la successiva UIViewController nello stack e si animerà da sinistra (insieme alla vista precedente), quando si premere il pulsante Indietro su UINavigationBar.

Nota che questi non sono metodi delegati, stai superando l'implementazione di <=> di questi metodi e, secondo la documentazione che devi chiamare l'implementazione del super da qualche parte nella tua implementazione .

Altri suggerimenti

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

navigationController.delegate = self;

e usa setNavigationBarHidden in 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];
}

Modo semplice per personalizzare il comportamento di ciascun ViewController tutto in un unico posto.

Una leggera modifica che ho dovuto apportare alle altre risposte è quella di scoprire la barra in viewWillDisappear se il motivo per cui sta scomparendo è dovuto al fatto che un elemento di navigazione è stato premuto 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];
}

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

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

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 guardando il controller della vista principale.

Invece, la strategia di @Chad M. sull'uso di UINavigationControllerDelegate è buona, e qui è una soluzione più completa. Passi:

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

Il codice completo per questa soluzione è disponibile in this Gist . Ecco l'implementazione 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];
    }
}

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 viewDidAppear, 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 viewWillAppear, 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.
}

passaggio 2.3 - Sotto viewWillDisappear, 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 in <=>, assicurati di rimettere tutto a posto

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

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

Ecco la versione di 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 MyNavigationController Questo è tutto!

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

  1. Eredita da UINavigationController, quindi non inquinerai rootViewController.

  2. usa self.viewControllers.first anziché homeViewController, quindi non lo farai 100 volte per i tuoi 100 UINavigationController in 1 StoryBoard.

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

Riesco a risolvere questo problema ignorando viewDidLayoutSubviews, oltre a viewWillAppear/viewWillDisappear come 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 è perché il controller di visualizzazione radice (dove è nascosto il navigatore) e il controller di visualizzazione push (viene mostrato il navigatore) ha diversi stili della barra di stato (ad esempio buio e luce ). 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.

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 vuoi visualizzarlo solo nel figlio, aggiungi il codice per visualizzare it(self.navigationController.navigationBarHidden=NO;) nel viewWillAppear callback, e allo stesso modo il codice per nasconderlo su viewWillDisappear

L'implementazione più semplice potrebbe essere quella di fare in modo che ciascun controller di visualizzazione specifichi se la sua barra di navigazione è nascosta o meno nel suo metodo viewWillAppear:animated:. 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];
}

È possibile nascondere la barra di navigazione solo nella prima pagina tramite lo storyboard. Nello storyboard, vai a Scena del controller di navigazione - & Gt; barra di navigazione . E seleziona la proprietà ' Nascosto ' da Impostazioni 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];                                                  
}

Swift 4:

Nel controller di visualizzazione da cui 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)
}

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];
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top