iPhone ocultar la barra de navegación solo en la primera página

383

Tengo el siguiente código que oculta y muestra la barra de navegación. Se oculta cuando se carga la primera vista y luego se oculta cuando se llama a los "hijos". El problema es que no puedo encontrar el evento / acción para que se oculte nuevamente cuando vuelven a la vista raíz ...

Tengo un botón de "prueba" en la página raíz que realiza la acción manualmente, pero no es bonito y quiero que sea automático.

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

Respuestas:

1036

La mejor solución que he encontrado es hacer lo siguiente en el primer controlador de vista .

C objetivo

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

Rápido

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

Esto hará que la barra de navegación se anime desde la izquierda (junto con la siguiente vista) cuando presiona el siguiente UIViewControlleren la pila, y se aleje hacia la izquierda (junto con la vista anterior), cuando presiona el botón Atrás en el UINavigationBar.

Tenga en cuenta también que estos no son métodos delegados, está anulando UIViewControllerla implementación de estos métodos y, de acuerdo con la documentación, debe llamar a la implementación del super en algún lugar de su implementación .

Alan Rogers
fuente
2
Esto es totalmente genial! Había estado luchando con esto durante al menos un día. ¡¡¡Gracias!!!
James Testa
26
ADVERTENCIA: Esto crea un error muy grave cuando se realiza un retroceso rápido. Suponga que A (sin barra de navegación) y B (con barra de navegación) empujados a la pila. Cuando está en la vista B y hace un retroceso rápido, pero suelte lo suficientemente temprano como para permanecer en B, la barra de navegación aún se oculta. Ahora ya no hay forma de volver. Esto se debe a animated=YES. Sé que parece feo animated=NO, pero parece que cuando la animación para ocultar la barra de navegación aún no está terminada, entonces se ignora la animación para mostrarla nuevamente. Aún no hay solución.
fabb
3
En Swift: override func viewWillAppear (animado: Bool) {self.navigationController? .SetNavigationBarHidden (verdadero, animado: verdadero) super.viewWillAppear (true)} anula func viewWillDisappear (animado: Bool) {self.navigationController? .SetNavigationBarHarid false, Barid false, Barid animado: falso) super.viewWillDisappear (verdadero)}
Kitson
77
¡La pregunta fue respondida en 2010 y me ayuda a fines de 2015! Gracias.
oyalhi
1
Ahora eso es lo que yo llamo una respuesta legendaria. Excelente truco compañero. Incluso trabajando después de décadas ... Implementado lo mismo de manera rápida, trabajando sin problemas. +1 por su respuesta @Alan Rogers
onCompletion
62

Otro enfoque que encontré es establecer un delegado para NavigationController :

navigationController.delegate = self;

y use setNavigationBarHidden ennavigationController: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];
}

Manera fácil de personalizar el comportamiento de cada ViewControlleruno en un solo lugar.

Chad M.
fuente
¿Cuándo se llamará esto?
Zalak Patel
1
Solución perfecta. Esta debería ser la respuesta aceptada. ¡Gracias!
Samah
Respuesta perfecta. También funciona en caso de que no podamos anular los métodos viewWillAppear y viewWillDisappear en el primer controlador de vista.
pjuzeliunas
1
Increíble. La respuesta elegida funciona bien, sin embargo, solo en aplicaciones simples. Esta respuesta funciona cuando la barra de navegación está en un controlador de pestañas y empuja / presenta varios VC de varias maneras.
Jonathan Winger-Lang
Esta es la mejor respuesta. La respuesta principal puede ocurrir un error como la descripción de @ fabb .
Ryan.Yuen
19

Una pequeña modificación que tuve que hacer en las otras respuestas es solo mostrar la barra en viewWillDisappear si la razón por la que está desapareciendo se debe a un elemento de navegación presionado sobre ella. Esto se debe a que la vista puede desaparecer por otros motivos.

Así que solo mostraré la barra si esta vista ya no es la vista superior:

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

    [super viewWillDisappear:animated];
}

fuente
3
+1, generalmente no desea mostrar la barra de navegación al presionar un diálogo modal.
João Portela
18

Pondría el código en la vista delegado en cada vista que se muestra:

Así, donde necesitas ocultarlo:

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

Como este donde necesitas mostrarlo:

- (void)viewWillAppear:(BOOL)animated
{
        [yourObject showBar];
}
Pablo Santa Cruz
fuente
Lee, si esto solucionó tu problema, marca la respuesta de Pablo como la "solución".
Rog
2
El único problema con esto es que la barra de navegación "aparece" a la vista mientras navega de una vista a la siguiente. ¿Es posible que la barra de navegación no esté allí en la primera vista, y cuando la segunda vista se desliza en su lugar, tiene la barra de navegación, sin ningún estallido?
Henning el
2
@henning Para hacer que la barra de navegación se deslice hacia adentro / afuera como se espera, debe usar setNavigationBarHidden: animated :. Vea la respuesta de Alan Rogers a continuación (que realmente debería marcarse como la "solución").
Nick Forge
2
Esta respuesta es un poco incorrecta (viewWill / DidAppear) debería estar llamando super. También vea mi respuesta a continuación para obtener una solución en la que no necesita agregarla a CADA controlador de vista.
Alan Rogers
15

La respuesta actualmente aceptada no coincide con el comportamiento previsto descrito en la pregunta. La pregunta solicita que la barra de navegación esté oculta en el controlador de vista raíz, pero visible en cualquier otro lugar, pero la respuesta aceptada oculta la barra de navegación en un controlador de vista particular. ¿Qué sucede cuando otra instancia del primer controlador de vista se inserta en la pila? Ocultará la barra de navegación aunque no estemos mirando el controlador de vista raíz.

En cambio, la estrategia de @Chad M. de usar el UINavigationControllerDelegatees buena, y aquí hay una solución más completa. Pasos:

  1. Subclase UINavigationController
  2. Implementar el -navigationController:willShowViewController:animated método para mostrar u ocultar la barra de navegación en función de si muestra el controlador de vista raíz
  3. Anule los métodos de inicialización para establecer la subclase UINavigationController como su propio delegado

El código completo para esta solución se puede encontrar en este Gist . Aquí está la navigationController:willShowViewController:animatedimplementación:

- (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];
    }
}
hunteros
fuente
2
Esta es una respuesta más apropiada que la aceptada
Pavel Gurov
14

en 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)
}
Eugene Braginets
fuente
¿podría explicar por qué busca! = self?
Kitson
2
@Kitson, verifique la respuesta del usuario 486646: un pequeño ajuste que tuve que hacer en las otras respuestas es solo mostrar la barra en viewWillDisappear si la razón por la que está desapareciendo se debe a que se presionó un elemento de navegación sobre ella. Esto se debe a que la vista puede desaparecer por otros motivos. Así que solo mostraré la barra si esta vista ya no es la más alta
Eugene Braginets
Parece que si usa el navcontroller.navagationBarHiddense romperá todo el controlador de navegación (sin deslizar hacia adelante y hacia atrás). Para que funcione, utilicé en su navigationController?.navigationBar.hiddenlugar. Deslizar todavía funciona y no deja espacio vacío porque parece estar dentro de una vista de pila o algo así
Sirenas
8

Dale mi crédito a la respuesta de @ chad-m.

Aquí está la versión Swift:

  1. Crea un nuevo archivo 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. Configure su clase de UINavigationController en StoryBoard en MyNavigationController ¡ Eso es!MyNavigationController

Diferencia entre la respuesta de chad-m y la mía:

  1. Herede de UINavigationController, por lo que no contaminará su rootViewController.

  2. use en self.viewControllers.firstlugar de homeViewController, por lo que no hará esto 100 veces para sus 100 UINavigationControllers en 1 StoryBoard.

AI Lion
fuente
Piensa que esta es la respuesta más limpia. Gracias
DaSilva
6

Después de varias pruebas aquí es cómo lo hice funcionar para lo que quería. Esto es lo que estaba intentando. - Tengo una vista con una imagen. y quería que la imagen pasara a pantalla completa. - Tengo un controlador de navegación con una barra de pestañas también. Entonces necesito ocultar eso también. - Además, mi requisito principal no era solo esconderme, sino también tener un efecto de desvanecimiento al mostrar y ocultar.

Así es como lo hice funcionar.

Paso 1: tengo una imagen y el usuario toca esa imagen una vez. Capturo ese gesto y lo introduzco en el nuevo imageViewController, está en el imageViewController, quiero tener una imagen de pantalla completa.

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

Paso 2: todos estos pasos a continuación se encuentran en ImageViewController

Paso 2.1 - En ViewDidLoad, muestra la barra de navegación

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

Paso 2.2 - En viewDidAppear, configure una tarea de temporizador con retraso (lo tengo configurado para 1 segundo de retraso). Y después del retraso, agregue efecto de desvanecimiento. Estoy usando alfa para usar el desvanecimiento.

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

paso 2.3: debajo viewWillAppear, agrega un gesto SingleTap a la imagen y haz que la barra de navegación sea translúcida.

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

Paso 3 - Finalmente viewWillDisappear, asegúrate de volver a poner todo

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

En caso de que alguien todavía tenga problemas con el error de cancelación rápida de backswipe como @fabb comentó en la respuesta aceptada.

Me las arreglo para anular esto viewDidLayoutSubviews, además de lo viewWillAppear/viewWillDisappearque se muestra a continuación:

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

En mi caso, noto que se debe a que el controlador de vista raíz (donde se oculta la navegación) y el controlador de vista presionado (se muestra la navegación) tiene diferentes estilos de barra de estado (por ejemplo, oscuro y claro). En el momento en que inicie el movimiento hacia atrás para mostrar el controlador de vista, habrá una animación de color de la barra de estado adicional. Si suelta el dedo para cancelar el pop interactivo, mientras la animación de la barra de estado no está terminada , la barra de navegación desaparece para siempre.

Sin embargo, este error no ocurre si los estilos de barra de estado de ambos controladores de vista son los mismos.

aunnnn
fuente
1

Si lo que desea es ocultar completamente la barra de navegación en el controlador, una solución mucho más limpia es, en el controlador raíz, tener algo como:

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

Cuando presiona una vista secundaria en el controlador, la barra de navegación permanecerá oculta; si desea mostrarlo solo en el elemento secundario, agregará el código para mostrar it(self.navigationController.navigationBarHidden=NO;)en la viewWillAppeardevolución de llamada y, de manera similar, el código para ocultarloviewWillDisappear

Alex
fuente
0

La implementación más simple puede ser que cada controlador de vista especifique si su barra de navegación está oculta o no en su viewWillAppear:animated:método. El mismo enfoque funciona bien para ocultar / mostrar la barra de herramientas también:

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setToolbarHidden:YES/NO animated:animated];
    [super viewWillAppear:animated];
}
SteveCaine
fuente
En realidad, mi sugerencia solo tiene sentido para la barra de herramientas, ya que ocultar la barra de navegación sin una llamada coincidente para mostrarla dejaría a los usuarios incapaces de navegar desde la vista actual.
SteveCaine
0

Ocultar la barra de navegación solo en la primera página también se puede lograr a través del guión gráfico. En el guión gráfico, vaya a Escena del controlador de navegación-> Barra de navegación . Y seleccione la propiedad ' Oculta ' del inspector de atributos . Esto ocultará la barra de navegación desde el primer controlador de vista hasta que se haga visible para el controlador de vista requerido.

La barra de navegación se puede volver a configurar en visible en la devolución de llamada ViewWillAppear de ViewController.

-(void)viewWillAppear:(BOOL)animated {

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

Swift 4:

En el controlador de vista del que desea ocultar la barra de navegación.

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

Al implementar este código en su ViewController, puede obtener este efecto. En realidad, el truco es ocultar la barra de navegación cuando se inicia ese controlador

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

y mostrar la barra de navegación cuando el usuario abandona esa página, hacer esto es viewWillDisappear

- (void)viewWillDisappear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:NO animated:YES];
    [super viewWillDisappear:animated];
}
Dhiru
fuente