Pregunta

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 & Quot; children & Quot; ser llamado El problema es que no puedo encontrar el evento / acción para activarlo para que se oculte nuevamente cuando vuelven a la vista raíz ...

Tengo un " test " botón 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;
}
¿Fue útil?

Solución

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

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

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

Tenga en cuenta también que estos no son métodos delegados, está anulando la implementación de <=> 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 .

Otros consejos

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

navigationController.delegate = self;

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

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

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 que se presionó un elemento de navegación sobre ella. Esto se debe a que la vista puede desaparecer por otros motivos.

Por lo tanto, 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];
}

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

Te gusta esto donde necesitas ocultarlo:

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

Te gusta esto donde necesitas mostrarlo:

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

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

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 UINavigationControllerDelegate es buena, y aquí está Una solución más completa. Pasos:

  1. Subclase UINavigationController
  2. Implemente el método -navigationController:willShowViewController:animated para mostrar u ocultar la barra de navegación en función de si muestra el controlador de vista raíz
  3. Reemplazar 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:animated implementació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];
    }
}

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 viewDidAppear, 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, muestre 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 viewWillAppear, 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: en viewWillDisappear, agregue un gesto de SingleTap a la imagen y haga 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, en <=>, asegúrese de volver a colocar 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];
}

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

Aquí está la versión Swift:

  1. Crear 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. Establezca la clase de UINavigationController en StoryBoard en MyNavigationController MyNavigationController ¡Eso es!

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

  1. Herede de UINavigationController, para que no contamine su rootViewController.

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

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

Me las arreglo para solucionar esto anulando viewDidLayoutSubviews, además de viewWillAppear/viewWillDisappear como 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 push (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.

Si lo que quiere es ocultar la barra de navegación completamente 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 devolución de llamada viewWillAppear y, de manera similar, el código para ocultarlo en viewWillDisappear

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 método viewWillAppear:animated:. 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];
}

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 - & Gt; Barra de navegación . Y seleccione la propiedad ' Oculto ' 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];                                                  
}

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

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 abandone esa página, haga clic en viewWillDisappear

- (void)viewWillDisappear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:NO animated:YES];
    [super viewWillDisappear:animated];
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top