iPhone Navigationsleiste nur auf der ersten Seite ausblenden

381

Ich habe den Code darunter, der die Navigationsleiste verbirgt und anzeigt. Es wird ausgeblendet, wenn die erste Ansicht geladen wird, und dann ausgeblendet, wenn die "Kinder" aufgerufen werden. Das Problem ist, dass ich das Ereignis / die Aktion zum Auslösen nicht finden kann, wenn sie zur Stammansicht zurückkehren.

Ich habe eine "Test" -Schaltfläche auf der Stammseite, die die Aktion manuell ausführt, aber sie ist nicht schön und ich möchte, dass sie automatisch erfolgt.

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

Antworten:

1035

Die schönste Lösung, die ich gefunden habe, besteht darin, im ersten Ansichts-Controller Folgendes zu tun .

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

Schnell

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

Dadurch wird die Navigationsleiste von links (zusammen mit der nächsten Ansicht) UIViewControlleranimiert, wenn Sie die nächste auf dem Stapel drücken , und von links (zusammen mit der alten Ansicht) animiert, wenn Sie die Zurück-Taste auf dem Stapel drücken UINavigationBar.

Bitte beachten Sie auch, dass dies keine delegierten Methoden sind, Sie die UIViewControllerImplementierung dieser Methoden überschreiben und gemäß der Dokumentation die Implementierung des Super irgendwo in Ihrer Implementierung aufrufen müssen .

Alan Rogers
quelle
2
Das rockt total! Ich hatte mindestens einen Tag damit zu kämpfen. Vielen Dank!!!
James Testa
26
WARNUNG: Dies führt bei einem schnellen Backswipe zu einem sehr schlimmen Fehler. Angenommen, A (keine Navigationsleiste) und B (mit Navigationsleiste) werden auf den Stapel geschoben. Wenn Sie in Ansicht B sind und einen schnellen Backswipe ausführen, diese jedoch früh genug loslassen, um auf B zu bleiben, wird die Navigationsleiste weiterhin ausgeblendet. Jetzt gibt es keinen Weg mehr zurück. Das liegt an animated=YES. Ich weiß, dass es hässlich aussieht animated=NO, aber wenn die Animation zum Ausblenden der Navigationsleiste noch nicht fertig ist, wird die Animation zum erneuten Anzeigen ignoriert. Noch keine Lösung.
Fabb
3
In Swift: func viewWillAppear überschreiben (animiert: Bool) {self.navigationController? .SetNavigationBarHidden (true, animiert: true) super.viewWillAppear (true)} func viewWillDisappear überschreiben (animiert: Bool) {self.navigationController? .SetNavigationBarHidden (false, animiert: false) super.viewWillDisappear (true)}
Kitson
7
Die Frage wurde 2010 beantwortet und hilft mir Ende 2015! Vielen Dank.
Oyalhi
1
Das nenne ich eine legendäre Antwort. Hervorragender Trickkamerad. Sogar nach Jahrzehnten arbeiten ... Gleiches schnell und fehlerfrei umgesetzt. +1 für Ihre Antwort @Alan Rogers
onCompletion
62

Ein anderer Ansatz, den ich gefunden habe, besteht darin, einen Delegierten für Folgendes festzulegen NavigationController:

navigationController.delegate = self;

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

Einfache Möglichkeit, das Verhalten für ViewControlleralle an einem Ort anzupassen .

Chad M.
quelle
Wann wird das aufgerufen?
Zalak Patel
1
Perfekte Lösung. Dies sollte die akzeptierte Antwort sein. Vielen Dank!
Samah
Perfekte Antwort. Dies funktioniert auch, wenn die Methoden viewWillAppear und viewWillDisappear auf dem ersten View-Controller nicht überschrieben werden können.
pjuzeliunas
1
Genial. Die gewählte Antwort funktioniert einwandfrei, jedoch nur in einfachen Apps. Diese Antwort funktioniert, wenn sich die Navigationsleiste in einem Tab-Controller befindet und verschiedene VCs auf verschiedene Arten pusht / präsentiert.
Jonathan Winger-Lang
Dies ist die beste Antwort. Die Top-Antwort kann ein Fehler als Beschreibung von @ fabb sein .
Ryan.Yuen
18

Eine kleine Änderung, die ich an den anderen Antworten vornehmen musste, besteht darin, die Leiste in viewWillDisappear nur dann einzublenden, wenn der Grund dafür ist, dass sie verschwindet, weil ein Navigationselement darauf gedrückt wird. Dies liegt daran, dass die Ansicht aus anderen Gründen verschwinden kann.

Daher mache ich die Leiste nur dann wieder sichtbar, wenn diese Ansicht nicht mehr die oberste Ansicht ist:

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

    [super viewWillDisappear:animated];
}

quelle
3
+1, normalerweise möchten Sie die Navigationsleiste nicht anzeigen, wenn Sie einen modalen Dialog drücken.
João Portela
17

Ich würde den Code in den viewWillAppear- Delegaten für jede angezeigte Ansicht einfügen :

So, wo Sie es verstecken müssen:

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

So, wo Sie es zeigen müssen:

- (void)viewWillAppear:(BOOL)animated
{
        [yourObject showBar];
}
Pablo Santa Cruz
quelle
Lee, wenn dies Ihr Problem behoben hat, markieren Sie Pablos als "Lösungs" -Antwort.
Rog
2
Das einzige Problem dabei ist, dass die Navigationsleiste beim Navigieren von einer Ansicht zur nächsten "herausspringt" und angezeigt wird. Ist es möglich, dass die Navigationsleiste in der ersten Ansicht nicht vorhanden ist, und wenn die zweite Ansicht einrastet, wird die Navigationsleiste angezeigt, ohne dass ein Knallen auftritt?
Henning
2
@henning Damit die NavBar wie erwartet ein- und ausgeblendet wird, müssen Sie setNavigationBarHidden: animiert: verwenden. Siehe die Antwort von Alan Rogers unten (die eigentlich als "Lösung" gekennzeichnet sein sollte).
Nick Forge
2
Diese Antwort ist etwas falsch (viewWill / DidAppear) sollte super anrufen. Siehe auch meine Antwort unten für eine Lösung, bei der Sie sie nicht JEDEM Ansichts-Controller hinzufügen müssen.
Alan Rogers
15

Die aktuell akzeptierte Antwort stimmt nicht mit dem in der Frage beschriebenen beabsichtigten Verhalten überein. In der Frage wird gefragt, ob die Navigationsleiste auf dem Root-View-Controller ausgeblendet, aber überall sichtbar ist. Die akzeptierte Antwort verbirgt jedoch die Navigationsleiste auf einem bestimmten View-Controller. Was passiert, wenn eine andere Instanz des ersten View Controllers auf den Stack verschoben wird? Die Navigationsleiste wird ausgeblendet, obwohl wir nicht auf den Root-View-Controller schauen.

Stattdessen ist die Strategie von @Chad M., das zu verwenden, UINavigationControllerDelegategut, und hier ist eine vollständigere Lösung. Schritte:

  1. Unterklasse UINavigationController
  2. Implementieren Sie die -navigationController:willShowViewController:animatedMethode zum Ein- oder Ausblenden der Navigationsleiste, je nachdem, ob der Root-View-Controller angezeigt wird
  3. Überschreiben Sie die Initialisierungsmethoden, um die UINavigationController-Unterklasse als eigenen Delegaten festzulegen

Den vollständigen Code für diese Lösung finden Sie in dieser Übersicht . Hier ist die navigationController:willShowViewController:animatedImplementierung:

- (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];
    }
}
Jäger
quelle
2
Dies ist eine angemessenere Antwort als die akzeptierte
Pavel Gurov
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)
}
Eugene Braginets
quelle
Können Sie erklären, warum Sie nach! = self suchen?
Kitson
2
@Kitson, überprüfen Sie die Antwort von user486646: Eine kleine
Eugene Braginets
Es scheint, dass wenn Sie das verwenden, navcontroller.navagationBarHiddenes den gesamten Navigationscontroller kaputt macht (kein Hin- und Herwischen). Um es zum Laufen zu bringen, habe ich navigationController?.navigationBar.hiddenstattdessen verwendet. Das Wischen funktioniert immer noch und es lässt keinen leeren Raum, weil es sich in einer Stapelansicht oder so zu befinden scheint
Sirenen
8

Geben Sie der Antwort von @ chad-m meine Ehre.

Hier ist die Swift-Version:

  1. Erstellen Sie eine neue Datei 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. Setzen Sie die Klasse Ihres UINavigationController in StoryBoard auf MyNavigationController. Das war's!MyNavigationController

Unterschied zwischen der Antwort von chad-m und meiner:

  1. Erben Sie von UINavigationController, damit Sie Ihren rootViewController nicht verschmutzen.

  2. Verwenden Sie self.viewControllers.firststatt homeViewController, damit Sie dies nicht 100 Mal für Ihre 100 UINavigationController in 1 StoryBoard tun.

AI Lion
quelle
Ich denke, das ist die sauberste Antwort. Danke
DaSilva
6

Nach mehreren Versuchen hier ist, wie ich es für das, was ich wollte, zum Laufen gebracht habe. Das habe ich versucht. - Ich habe eine Ansicht mit einem Bild. und ich wollte, dass das Bild im Vollbildmodus angezeigt wird. - Ich habe auch einen Navigationscontroller mit einer TabBar. Also muss ich das auch verstecken. - Außerdem war meine Hauptanforderung, mich nicht nur zu verstecken, sondern auch beim Ein- und Ausblenden einen verblassenden Effekt zu haben.

So habe ich es zum Laufen gebracht.

Schritt 1 - Ich habe ein Bild und der Benutzer tippt einmal auf dieses Bild. Ich fange diese Geste ein und schiebe sie in das Neue imageViewController, es ist in der imageViewController, ich möchte ein Vollbild haben.

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

Schritt 2 - Alle folgenden Schritte befinden sich im ImageViewController

Schritt 2.1 - Zeigen Sie in ViewDidLoad die Navigationsleiste an

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

Schritt 2.2 - viewDidAppearRichten Sie eine Timer-Task mit Verzögerung ein (ich habe sie auf 1 Sek. Verzögerung eingestellt). Fügen Sie nach der Verzögerung einen Fading-Effekt hinzu. Ich benutze Alpha, um Fading zu verwenden.

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

Schritt 2.3 - viewWillAppearFügen Sie unter SingleTap-Geste zum Bild hinzu und machen Sie die navBar durchscheinend.

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

Schritt 3 - Stellen Sie schließlich viewWillDisappearsicher, dass Sie alle Sachen zurücklegen

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

Für den Fall, dass jemand immer noch Probleme mit dem abgebrochenen schnellen Backswipe-Fehler hat, wie @fabb in der akzeptierten Antwort kommentiert hat.

Ich schaffe es, dies durch Überschreiben zu beheben viewDidLayoutSubviews, zusätzlich viewWillAppear/viewWillDisappearwie unten gezeigt:

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

In meinem Fall stelle ich fest, dass der Root-View-Controller (wo nav ausgeblendet ist) und der Push-View-Controller (nav wird angezeigt) unterschiedliche Statusleistenstile haben (z. B. dunkel und hell). Sobald Sie den Backswipe starten, um den Ansichts-Controller zu öffnen, wird eine zusätzliche Farbanimation in der Statusleiste angezeigt. Wenn Sie Ihren Finger loslassen, um den interaktiven Pop abzubrechen, während die Statusleistenanimation noch nicht abgeschlossen ist , ist die Navigationsleiste für immer verschwunden!

Dieser Fehler tritt jedoch nicht auf, wenn die Statusleistenstile beider Ansichtssteuerungen identisch sind.

aunnnn
quelle
1

Wenn Sie die Navigationsleiste vollständig im Controller ausblenden möchten, besteht eine viel sauberere Lösung darin, im Root-Controller Folgendes zu haben:

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

Wenn Sie eine untergeordnete Ansicht in der Steuerung verschieben, bleibt die Navigationsleiste ausgeblendet. Wenn Sie es nur im untergeordneten Element anzeigen möchten, fügen Sie den Code zum Anzeigen it(self.navigationController.navigationBarHidden=NO;)im viewWillAppearRückruf und den Code zum Ausblenden hinzuviewWillDisappear

Alex
quelle
0

Die einfachste Implementierung kann darin bestehen, dass jeder Ansichts-Controller angibt, ob seine Navigationsleiste in seiner viewWillAppear:animated:Methode ausgeblendet ist oder nicht . Der gleiche Ansatz eignet sich auch zum Ausblenden / Anzeigen der Symbolleiste:

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setToolbarHidden:YES/NO animated:animated];
    [super viewWillAppear:animated];
}
SteveCaine
quelle
Eigentlich macht mein Vorschlag nur für die Symbolleiste Sinn, da das Ausblenden der Navigationsleiste ohne einen passenden Aufruf zur Anzeige dazu führen würde, dass Benutzer nicht mehr aus der aktuellen Ansicht zurückkehren können.
SteveCaine
0

Das Ausblenden der Navigationsleiste nur auf der ersten Seite kann auch über das Storyboard erreicht werden. Gehen Sie im Storyboard zu Navigation Controller Scene-> Navigation Bar . Wählen Sie im Inspektor "Attribute " die Eigenschaft " Versteckt " . Dadurch wird die Navigationsleiste vom ersten Ansichtscontroller ausgeblendet, bis sie für den erforderlichen Ansichtscontroller sichtbar wird.

Die Navigationsleiste kann im ViewWillAppear-Rückruf von ViewController wieder sichtbar gemacht werden.

-(void)viewWillAppear:(BOOL)animated {

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

Swift 4:

In der Ansichtssteuerung möchten Sie die Navigationsleiste ausblenden.

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

Wenn Sie diesen Code in Ihrem ViewController implementieren, können Sie diesen Effekt erzielen. Der eigentliche Trick besteht darin, die Navigationsleiste beim Starten dieses Controllers auszublenden

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

und die Navigationsleiste einblenden, wenn der Benutzer diese Seite verlässt, ist viewWillDisappear

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