iPhone hide Barra de navegação apenas na primeira página

381

Eu tenho o código abaixo que oculta e mostra a barra de navegação. Ele fica oculto quando a primeira exibição é carregada e depois oculto quando os "filhos" são chamados. O problema é que não consigo encontrar o evento / ação para acioná-lo para ocultar novamente quando eles retornam à visualização raiz ....

Eu tenho um botão "teste" na página raiz que executa a ação manualmente, mas não é bonito e quero que seja automático.

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

Respostas:

1035

A melhor solução que encontrei é fazer o seguinte no primeiro controlador de exibição .

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

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

Isso fará com que a barra de navegação seja animada da esquerda (junto com a próxima exibição) quando você empurra a próxima UIViewControllerna pilha e animada para a esquerda (junto com a exibição antiga), quando você pressiona o botão voltar na UINavigationBar.

Observe também que esses não são métodos delegados, você está substituindo UIViewControllera implementação desses métodos e, de acordo com a documentação, deve chamar a implementação do super em algum lugar da sua implementação .

Alan Rogers
fonte
2
Isso é demais! Eu estava lutando com isso por pelo menos um dia. Obrigado!!!
James Testa
26
AVISO: Isso cria um bug muito ruim ao fazer um backswipe rápido. Suponha que A (sem barra de navegação) e B (com barra de navegação) sejam empurrados para a pilha. Quando visualiza B e faz um retrocesso rápido, mas libera cedo o suficiente para permanecer em B, a barra de navegação ainda fica oculta. Agora não há mais como voltar atrás. Isto é devido a animated=YES. Eu sei que parece feio animated=NO, mas parece que quando a animação para ocultar a barra de navegação ainda não está concluída, a animação para mostrá-la novamente é ignorada. Ainda não há solução.
Fabb
3
Em Swift: substituir func viewWillAppear (animado: Bool) {self.navigationController? .SetNavigationBarHidden (true, animado: true) super.viewWillAppear (true)} substituir func viewWillDisappear (animado: Bool) {self.navigationController? .SetNavigationBarHidden (false, animado: false) super.viewWillDisappear (true)}
Kitson
7
A pergunta foi respondida em 2010 e me ajuda no final de 2015! Obrigado.
oyalhi 8/12
11
Agora é isso que chamo de resposta lendária. Excelente truque companheiro. Mesmo trabalhando depois de décadas ... Implementou o mesmo rapidamente, trabalhando na perfeição. +1 para sua resposta @ Alan Rogers
onCompletion
62

Outra abordagem que encontrei é definir um delegado para NavigationController:

navigationController.delegate = self;

e usar setNavigationBarHiddenemnavigationController: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];
}

Maneira fácil de personalizar o comportamento de cada ViewControllerum em um só lugar.

Chad M.
fonte
Quando isso será chamado?
Zalak Patel
11
Solução perfeita. Essa deve ser a resposta aceita. Obrigado!
Samah 01/02
Resposta perfeita. Também funciona caso não possamos substituir os métodos viewWillAppear e viewWillDisappear no primeiro controlador de exibição.
Pjuzeliunas 26/10/16
11
Impressionante. A resposta escolhida funciona bem, no entanto, apenas em aplicativos simples. Essa resposta funciona quando a barra de navegação está em um controlador de guia e pressiona / apresenta vários VCs de várias maneiras.
Jonathan Winger-Lang
Esta é a melhor resposta. A resposta superior pode ocorrer um erro como a descrição do @ fabb .
precisa saber é o seguinte
18

Um pequeno ajuste que eu tive que fazer nas outras respostas é mostrar apenas a barra no viewWillDisappear se o motivo pelo qual está desaparecendo se deve ao fato de um item de navegação ser pressionado nela. Isso ocorre porque a exibição pode desaparecer por outros motivos.

Então, só mostro a barra se essa visualização não for mais a mais alta:

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

    [super viewWillDisappear:animated];
}

fonte
3
+1, você geralmente não deseja mostrar a barra de navegação ao pressionar uma caixa de diálogo modal.
João Portela
17

Eu colocaria o código no delegado viewWillAppear em cada modo de exibição mostrado:

Assim, onde você precisa escondê-lo:

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

Assim, onde você precisa mostrá-lo:

- (void)viewWillAppear:(BOOL)animated
{
        [yourObject showBar];
}
Pablo Santa Cruz
fonte
Lee, se isso resolveu o seu problema, marque o de Pablo como a "solução".
Rog
2
O único problema com isso é que a barra de navegação "sai" e fica visível quando você navega de um modo para o outro. É possível simplesmente não ter a barra de navegação na primeira visualização e, quando a segunda visualização deslizar no lugar, ela possui a barra de navegação, sem estalar?
Henning
2
@henning Para fazer o NavBar deslizar para dentro / fora como seria de esperar, você precisa usar setNavigationBarHidden: animated :. Veja a resposta de Alan Rogers abaixo (que realmente deve ser marcada como a "solução").
Nick Forge
2
Esta resposta está um pouco errada (viewWill / DidAppear) deve estar chamando super. Veja também a minha resposta abaixo para uma solução em que você não precisa adicioná-la a TODOS os controladores de exibição.
Alan Rogers
15

A resposta atualmente aceita não corresponde ao comportamento pretendido descrito na pergunta. A pergunta solicita que a barra de navegação fique oculta no controlador de exibição raiz, mas visível em qualquer outro lugar, mas a resposta aceita oculta a barra de navegação em um controlador de exibição específico. O que acontece quando outra instância do primeiro controlador de exibição é colocada na pilha? Ele ocultará a barra de navegação, mesmo que não estejamos olhando para o controlador de visualização raiz.

Em vez disso, a estratégia de @Chad M. de usar o UINavigationControllerDelegateé boa e aqui está uma solução mais completa. Passos:

  1. Subclasse UINavigationController
  2. Implemente o -navigationController:willShowViewController:animatedmétodo para mostrar ou ocultar a barra de navegação com base em se está mostrando o controlador de visualização raiz
  3. Substitua os métodos de inicialização para definir a subclasse UINavigationController como seu próprio representante

O código completo para esta solução pode ser encontrado nesta lista . Aqui está a navigationController:willShowViewController:animatedimplementação:

- (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
fonte
2
Esta é uma resposta mais adequada do que a aceita
Pavel Gurov
14

no 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
fonte
você poderia explicar por que você verifica! = self?
Kitson
2
@ Kitson, verifique a resposta do user486646 ': um pequeno ajuste que eu tive que fazer nas outras respostas é apenas mostrar a barra no viewWillDisappear se o motivo pelo qual está desaparecendo é devido a um item de navegação pressionado nele. Isso ocorre porque a exibição pode desaparecer por outros motivos. Então eu só reexibir a barra se este ponto de vista não é mais o ponto de vista mais alto
Eugene Braginets
Parece que, se você usar, navcontroller.navagationBarHiddenele quebrará todo o controlador de navegação (sem passar para frente e para trás). Para fazê-lo funcionar, eu usei navigationController?.navigationBar.hidden. Passando ainda funciona e não deixar espaço vazio, porque parece estar dentro de um stackview ou algo
Sirens
8

Dê meu crédito à resposta de @ chad-m.

Aqui está a versão Swift:

  1. Crie um novo arquivo 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. Defina a classe do seu UINavigationController no StoryBoard como MyNavigationController É isso!MyNavigationController

Diferença entre a resposta de chad-m e a minha:

  1. Herdar de UINavigationController, para que você não polua seu rootViewController.

  2. use em self.viewControllers.firstvez de homeViewController, então você não fará isso 100 vezes para seus 100 UINavigationControllers em 1 StoryBoard.

AI Lion
fonte
Pense que esta é a resposta mais limpa. Graças
DaSilva
6

Após vários testes, aqui está como eu consegui que funcionasse para o que queria. Era isso que eu estava tentando. - Eu tenho uma visão com uma imagem. e eu queria que a imagem ficasse em tela cheia. - Eu tenho um controlador de navegação com uma tabBar também. Então eu preciso esconder isso também. - Além disso, meu principal requisito não era apenas ocultar, mas também ter um efeito de desbotamento ao mostrar e ocultar.

Foi assim que eu consegui funcionar.

Etapa 1 - Eu tenho uma imagem e o usuário toca nessa imagem uma vez. Capto esse gesto e o empurro para o novo imageViewController, é no imageViewController, quero ter uma imagem em tela cheia.

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

Etapa 2 - Todas essas etapas abaixo estão no ImageViewController

Etapa 2.1 - No ViewDidLoad, mostre a navBar

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

Etapa 2.2 - In viewDidAppear, configure uma tarefa de timer com atraso (eu tenho isso definido para 1 segundo de atraso). E após o atraso, adicione efeito de desbotamento. Eu estou usando alfa para usar desbotamento.

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

passo 2.3 - Abaixo viewWillAppear, adicione um gesto de toque único à imagem e torne a navBar 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];
 }

Etapa 3 - Finalmente viewWillDisappear, certifique-se de colocar todas as coisas de volta

- (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
fonte
4

Caso alguém ainda tenha problemas com o bug rápido de retrocesso cancelado, como o @fabb comentou na resposta aceita.

Consigo corrigir isso substituindo viewDidLayoutSubviews, além do viewWillAppear/viewWillDisappearmostrado abaixo:

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

No meu caso, noto que é porque o controlador de visualização raiz (onde nav está oculto) e o controlador de visualização pressionado (nav é mostrado) têm estilos diferentes de barra de status (por exemplo, escuro e claro). No momento em que você inicia o retrocesso para abrir o controlador de exibição, haverá animação adicional em cores na barra de status. Se você soltar o dedo para cancelar o pop interativo, enquanto a animação da barra de status não estiver concluída , a barra de navegação desaparecerá para sempre!

No entanto, esse erro não ocorre se os estilos da barra de status dos dois controladores de exibição forem os mesmos.

aunnnn
fonte
1

Se o que você deseja é ocultar completamente a barra de navegação no controlador, uma solução muito mais limpa é, no controlador raiz, ter algo como:

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

Quando você pressiona uma exibição filho no controlador, a Barra de Navegação permanece oculta; se você quiser exibi-lo apenas na criança, você adicionará o código para exibirit(self.navigationController.navigationBarHidden=NO;) no viewWillAppearretorno de chamada e, da mesma forma, o código para ocultá-loviewWillDisappear

Alex
fonte
0

A implementação mais simples pode ser apenas fazer com que cada controlador de exibição especifique se sua barra de navegação está oculta ou não em seu viewWillAppear:animated:método. A mesma abordagem funciona bem para ocultar / mostrar a barra de ferramentas também:

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setToolbarHidden:YES/NO animated:animated];
    [super viewWillAppear:animated];
}
SteveCaine
fonte
Na verdade, minha sugestão só faz sentido para a barra de ferramentas, pois ocultar a barra de navegação sem uma chamada correspondente para mostrar que deixaria os usuários incapazes de navegar de volta na exibição atual.
precisa saber é o seguinte
0

Ocultar a barra de navegação somente na primeira página também pode ser conseguida através do storyboard. No storyboard, vá para Navigation Controller Scene-> Navigation Bar . E selecione a propriedade ' Oculto ' no inspetor Atributos . Isso ocultará a barra de navegação, iniciando do primeiro viewcontroller até que fique visível para o viewcontroller necessário.

A barra de navegação pode ser configurada novamente como visível no retorno de chamada ViewWillAppear do ViewController.

-(void)viewWillAppear:(BOOL)animated {

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

Swift 4:

No controlador de exibição do qual você deseja ocultar a barra de navegação.

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
fonte
-1

Ao implementar esse código no seu ViewController, você pode obter esse efeito. Na verdade, o truque é ocultar a barra de navegação quando o controlador for iniciado.

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

e reexibir a barra de navegação quando o usuário sair dessa página, faça isso: viewWillDisappear

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