iPhone menyembunyikan Bilah Navigasi hanya di halaman pertama

382

Saya memiliki kode di bawah ini yang menyembunyikan dan menunjukkan bilah navigasi. Ini disembunyikan ketika tampilan pertama dimuat dan kemudian disembunyikan ketika "anak-anak" dipanggil. Masalahnya adalah bahwa saya tidak dapat menemukan acara / tindakan untuk memicunya bersembunyi lagi ketika mereka kembali ke tampilan root ....

Saya memiliki tombol "test" pada halaman root yang melakukan tindakan secara manual tetapi tidak cantik dan saya ingin otomatis.

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

Jawaban:

1035

Solusi terbaik yang saya temukan adalah dengan melakukan hal berikut pada controller tampilan pertama .

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

Cepat

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

Ini akan menyebabkan bilah navigasi untuk menghidupkan dari kiri (bersama-sama dengan tampilan berikutnya) ketika Anda mendorong berikutnya UIViewControllerpada tumpukan, dan menghidupkan jauh ke kiri (bersama-sama dengan tampilan yang lama), ketika Anda menekan tombol kembali pada UINavigationBar.

Harap perhatikan juga bahwa ini bukan metode yang didelegasikan, Anda sedang mengesampingkan UIViewControllerpenerapan metode ini, dan menurut dokumentasi Anda harus menghubungi implementasi super di suatu tempat dalam implementasi Anda .

Alan Rogers
sumber
2
Ini benar-benar batu! Saya telah berjuang dengan ini selama setidaknya satu hari. Terima kasih!!!
James Testa
26
PERINGATAN: Ini menciptakan bug yang sangat buruk ketika melakukan backswipe cepat. Asumsikan A (tanpa navbar) dan B (dengan navbar) didorong ke tumpukan. Ketika dilihat B dan melakukan backswipe cepat, tetapi rilis cukup awal untuk tetap di B, navbar masih disembunyikan. Sekarang tidak ada cara untuk kembali lagi. Ini karena animated=YES. Saya tahu ini terlihat jelek animated=NO, tetapi sepertinya animasi untuk menyembunyikan navbar belum selesai, maka animasi untuk menampilkannya lagi diabaikan. Belum ada solusi.
Fabb
3
Di Swift: override func viewWillAppear (animated: Bool) {self.navigationController? .SetNavigationBarHidden (true, animated: true) super.viewWillAppear (true)} override func viewWillDisappear (animated: Bool) {self.navigationController? .Set, Navigasi, palsu (palsu, palsu) animated: false) super.viewWillDisappear (true)}
Kitson
7
Pertanyaan dijawab pada 2010 dan membantu saya di akhir 2015! Terima kasih.
oyalhi
1
Nah, itu yang saya sebut jawaban legendaris. Teman trik yang luar biasa. Bahkan bekerja setelah berpuluh-puluh tahun ... Melaksanakan hal yang sama dengan cepat, bekerja dengan sempurna. +1 untuk jawaban Anda @Alan Rogers
onCompletion
62

Pendekatan lain yang saya temukan adalah menetapkan delegasi untuk NavigationController:

navigationController.delegate = self;

dan gunakan setNavigationBarHiddendinavigationController: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];
}

Cara mudah untuk menyesuaikan perilaku masing-masing ViewControllerdi satu tempat.

Chad M.
sumber
Kapan ini dipanggil?
Zalak Patel
1
Solusi sempurna. Ini harus menjadi jawaban yang diterima. Terima kasih!
Samah
Jawaban sempurna. Ini juga berfungsi jika kita tidak bisa mengganti metode viewWillAppear dan viewWillDisappear pada pengontrol tampilan pertama.
pjuzeliunas
1
Luar biasa. Jawaban yang dipilih berfungsi dengan baik, namun hanya di aplikasi sederhana. Jawaban ini berfungsi ketika bilah navigasi di tab controller dan mendorong / menyajikan berbagai VC dengan berbagai cara.
Jonathan Winger-Lang
Ini jawaban terbaik. Jawaban teratas dapat muncul bug sebagai deskripsi @ fabb .
Ryan.Yuen
19

Satu perubahan kecil yang harus saya lakukan pada jawaban yang lain adalah dengan hanya menyembunyikan bilah di viewWillDisappear jika alasannya menghilang adalah karena item navigasi didorong di atasnya. Ini karena tampilan dapat menghilang karena alasan lain.

Jadi saya hanya menyembunyikan bilah jika tampilan ini bukan lagi tampilan teratas:

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

    [super viewWillDisappear:animated];
}

sumber
3
+1, Anda biasanya tidak ingin menampilkan bilah navigasi saat mendorong dialog modal.
João Portela
17

Saya akan meletakkan kode di delegasi viewWillAppear pada setiap tampilan yang ditampilkan:

Seperti ini di mana Anda perlu menyembunyikannya:

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

Seperti ini di mana Anda perlu menunjukkannya:

- (void)viewWillAppear:(BOOL)animated
{
        [yourObject showBar];
}
Pablo Santa Cruz
sumber
Lee, jika ini memperbaiki masalah Anda, tandai Pablo sebagai jawaban "solusi".
Rog
2
Satu-satunya masalah dengan ini adalah bahwa bilah navigasi "muncul" dan masuk ke tampilan saat Anda menavigasi dari satu tampilan ke yang berikutnya. Apakah mungkin hanya memiliki bilah navigasi yang tidak ada pada tampilan pertama, dan ketika tampilan kedua meluncur ke tempatnya, bilah navigasi nav, tanpa muncul apa-apa?
Henning
2
@melakukan Untuk membuat slide NavBar masuk / keluar seperti yang Anda harapkan, Anda perlu menggunakan setNavigationBarHidden: animated :. Lihat jawaban Alan Rogers di bawah ini (yang harus benar-benar ditandai sebagai "solusi").
Nick Forge
2
Jawaban ini sedikit salah (viewWill / DidAppear) harus memanggil super. Lihat juga jawaban saya di bawah ini untuk solusi di mana Anda tidak perlu menambahkannya ke SETIAP controller tampilan.
Alan Rogers
15

Jawaban yang saat ini diterima tidak sesuai dengan perilaku yang dimaksudkan yang dijelaskan dalam pertanyaan. Pertanyaannya meminta bilah navigasi disembunyikan di pengontrol tampilan root, tetapi terlihat di tempat lain, tetapi jawaban yang diterima menyembunyikan bilah navigasi pada pengontrol tampilan tertentu. Apa yang terjadi ketika instance lain dari pengontrol tampilan pertama didorong ke stack? Ini akan menyembunyikan bilah navigasi meskipun kita tidak melihat pengontrol tampilan root.

Alih-alih, strategi @Chad M. untuk menggunakan UINavigationControllerDelegateadalah yang baik, dan di sini adalah solusi yang lebih lengkap. Langkah:

  1. Subkelas UINavigationController
  2. Menerapkan -navigationController:willShowViewController:animated metode untuk menampilkan atau menyembunyikan bilah navigasi berdasarkan apakah itu memperlihatkan pengontrol tampilan root
  3. Ganti metode inisialisasi untuk menetapkan subkelas UINavigationController sebagai delegasinya sendiri

Kode lengkap untuk solusi ini dapat ditemukan di Intisari ini . Inilah navigationController:willShowViewController:animatedimplementasinya:

- (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
sumber
2
Ini adalah jawaban yang lebih tepat daripada jawaban yang diterima
Pavel Gurov
14

dalam 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
sumber
dapatkah Anda menjelaskan mengapa Anda memeriksa! = sendiri?
Kitson
2
@ Kitson, periksa jawaban user486646 ': Satu sedikit
Eugene Braginets
Tampaknya jika Anda menggunakannya navcontroller.navagationBarHiddenakan merusak seluruh pengontrol navigasi (tidak ada gesekan bolak-balik). Untuk membuatnya bekerja, saya menggunakan navigationController?.navigationBar.hiddensebagai gantinya. Menggesekkan masih berfungsi dan tidak meninggalkan ruang kosong karena tampaknya berada di dalam stackview atau sesuatu
Sirens
8

Berikan kredit saya untuk jawaban @ chad-m.

Ini adalah versi Swift:

  1. Buat file baru 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. Atur kelas UINavigationController Anda di StoryBoard ke MyNavigationController Itu dia!MyNavigationController

Perbedaan antara jawaban chad-m dan milik saya:

  1. Mewarisi dari UINavigationController, sehingga Anda tidak akan mencemari rootViewController Anda.

  2. gunakan self.viewControllers.firstdaripada homeViewController, jadi Anda tidak akan melakukan ini 100 kali untuk 100 UINavigationControllers Anda dalam 1 StoryBoard.

AI Lion
sumber
Pikirkan ini adalah jawaban terbersih. Terima kasih
DaSilva
6

Setelah beberapa percobaan di sini adalah bagaimana saya membuatnya bekerja untuk apa yang saya inginkan. Ini yang saya coba. - Saya memiliki pandangan dengan gambar. dan saya ingin memiliki gambar layar penuh. - Saya memiliki pengontrol navigasi dengan tabBar juga. Jadi saya perlu menyembunyikannya juga. - Juga, persyaratan utama saya bukan hanya bersembunyi, tetapi memiliki efek memudar juga saat menunjukkan dan bersembunyi.

Beginilah cara saya membuatnya bekerja.

Langkah 1 - Saya memiliki gambar dan pengguna mengetuk gambar itu sekali. Saya menangkap gerakan itu dan mendorongnya ke yang baru imageViewController, di dalamnya imageViewController, saya ingin memiliki gambar layar penuh.

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

Langkah 2 - Semua langkah di bawah ini ada di ImageViewController

Langkah 2.1 - Di ViewDidLoad, tampilkan navBar

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

Langkah 2.2 - In viewDidAppear, atur tugas pengatur waktu dengan penundaan (Saya sudah mengaturnya untuk penundaan 1 detik). Dan setelah penundaan, tambahkan efek fading. Saya menggunakan alpha untuk menggunakan fading.

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

langkah 2.3 - Di bawah viewWillAppear, tambahkan gerakan singleTap ke gambar dan membuat navBar tembus.

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

Langkah 3 - Akhirnya viewWillDisappear, pastikan untuk mengembalikan semua barang

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

Jika ada yang masih mengalami masalah dengan bug dibatalkan fast backswipe seperti @fabb berkomentar dalam jawaban yang diterima.

Saya berhasil memperbaikinya dengan mengabaikan viewDidLayoutSubviews, selain viewWillAppear/viewWillDisappearseperti yang ditunjukkan di bawah ini:

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

Dalam kasus saya, saya perhatikan bahwa itu karena pengontrol tampilan root (di mana nav disembunyikan) dan pengontrol tampilan yang didorong (nav ditampilkan) memiliki gaya bilah status yang berbeda (mis. Gelap dan terang). Saat Anda memulai backswipe untuk memunculkan controller tampilan, akan ada animasi warna status bar tambahan. Jika Anda melepaskan jari Anda untuk membatalkan pop interaktif, sementara animasi status bar belum selesai , bilah navigasi selamanya hilang!

Namun, bug ini tidak terjadi jika gaya bilah status dari kedua pengontrol tampilan sama.

aunnnn
sumber
1

Jika yang Anda inginkan adalah menyembunyikan bilah navigasi sepenuhnya di dalam pengontrol, solusi yang lebih bersih adalah, di pengontrol root, memiliki sesuatu seperti:

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

Saat Anda mendorong tampilan anak di controller, Bilah Navigasi akan tetap tersembunyi; jika Anda ingin menampilkannya hanya pada anak, Anda akan menambahkan kode untuk ditampilkan it(self.navigationController.navigationBarHidden=NO;)di viewWillAppearcallback, dan juga kode untuk menyembunyikannya diviewWillDisappear

Alex
sumber
0

Implementasi yang paling sederhana adalah dengan meminta setiap pengontrol tampilan menentukan apakah bilah navigasinya tersembunyi atau tidak dalam viewWillAppear:animated:metodenya. Pendekatan yang sama berfungsi dengan baik untuk menyembunyikan / menampilkan toolbar juga:

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setToolbarHidden:YES/NO animated:animated];
    [super viewWillAppear:animated];
}
SteveCaine
sumber
Sebenarnya, saran saya hanya masuk akal untuk bilah alat, karena menyembunyikan bilah navigasi tanpa panggilan yang cocok untuk menunjukkannya akan membuat pengguna tidak dapat menavigasi kembali dari tampilan saat ini.
SteveCaine
0

Menyembunyikan bilah navigasi hanya pada halaman pertama dapat dicapai melalui storyboard juga. Pada storyboard, goto Navigation Controller Scene-> Navigation Bar . Dan pilih properti ' Tersembunyi ' dari inspektur Atribut . Ini akan menyembunyikan bilah navigasi mulai dari viewcontroller pertama hingga terlihat oleh viewcontroller yang diperlukan.

Bilah navigasi dapat diatur kembali agar terlihat di panggilan balik ViewWillAppear ViewController.

-(void)viewWillAppear:(BOOL)animated {

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

Swift 4:

Di pengontrol tampilan Anda ingin menyembunyikan bilah navigasi.

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

Dengan menerapkan kode ini di ViewController Anda, Anda bisa mendapatkan efek ini Sebenarnya triknya adalah, sembunyikan navigationBar ketika Controller itu diluncurkan

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

dan sembunyikan bilah navigasi ketika pengguna meninggalkan halaman itu lakukan ini viewWillDisappear

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