iPhoneは最初のページでのみナビゲーションバーを非表示にする


381

ナビゲーションバーを非表示にして表示する以下のコードがあります。最初のビューが読み込まれると非表示になり、「子」が呼び出されると非表示になります。問題は、ルートビューに戻ったときに、それをトリガーして再度非表示にするイベント/アクションが見つからないことです...

ルートページに手動でアクションを実行する「テスト」ボタンがありますが、見栄えがよくないので、自動にしたいと思います。

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

回答:


1035

私が見つけた最も良い解決策は、最初のビューコントローラーで以下を実行することです。

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

迅速

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

これUIViewControllerにより、スタックの次を押すと、ナビゲーションバーが左から(次のビューと一緒に)アニメーションし、左の(古いビューと一緒に)を押すと、左側の[戻る]ボタンを押します。UINavigationBar

これらはデリゲートメソッドではなくUIViewController、これらのメソッドの実装をオーバーライドしていることにも注意してください。ドキュメントによると、実装のどこかでスーパーの実装を呼び出す必要あります


2
これはすごい!私はこれに少なくとも1日は苦労していました。ありがとう!!!
James Testa、2011

26
警告:高速バックスワイプを行うと、これは非常に悪いバグを作成します。スタックにプッシュされたA(ナビゲーションバーなし)およびB(ナビゲーションバーあり)を想定します。ビューBで高速バックスワイプを行っているが、Bにとどまるのに十分早い時期にリリースすると、ナビゲーションバーが非表示になります。もう戻る方法はありません。これはによるものanimated=YESです。で見栄えanimated=NOが悪いのはわかっていますが、ナビゲーションバーを非表示にするアニメーションがまだ終了していないようで、再度表示するアニメーションは無視されます。まだ解決策はありません。
2015

3
Swift:オーバーライドfunc viewWillAppear(animated:Bool){self.navigationController?.setNavigationBarHidden(true、animated:true)super.viewWillAppear(true)} override func viewWillDisappear(animated:Bool){self.navigationController?.setNavigationBarHidden(false animated:false)super.viewWillDisappear(true)}
Kitson

7
質問は2010年に回答され、2015年の終わりに私を助けてくれます!ありがとうございました。
oyalhi

1
それが伝説の答えです。素晴らしいトリックメイト。数十年後にも動作します...同じことを迅速に実装し、完璧に動作しました。回答の+1 @Alan Rogers
onCompletion

62

私が見つけた別のアプローチは、のデリゲートを設定することですNavigationController

navigationController.delegate = self;

そして、使用setNavigationBarHiddennavigationController: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];
}

ViewControllerすべての動作を1か所で簡単にカスタマイズできます。


これはいつ呼び出されますか?
Zalak Patel 14年

1
完璧なソリューション。これは受け入れられる答えになるはずです。ありがとう!
2016

完璧な答え。また、最初のビューコントローラーでviewWillAppearメソッドとviewWillDisappearメソッドをオーバーライドできない場合にも機能します。
pjuzeliunas

1
驚くばかり。選択した答えは問題ありませんが、シンプルなアプリでのみ機能します。この回答は、ナビゲーションバーがタブコントローラー内にあり、さまざまな方法でさまざまなVCをプッシュ/表示するときに機能します。
Jonathan Winger-Lang

これが最良の答えです。一番上の答えは@ fabbの説明としてバグが発生する可能性があります。
Ryan.Yuen 2018

18

他の答えに加えなければならないわずかな微調整の1つは、ナビゲーションアイテムがプッシュされているためにバーが非表示になっている場合は、viewWillDisappearでバーを再表示することだけです。これは、ビューが他の理由で消えることがあるためです。

したがって、このビューが最上位のビューではなくなった場合にのみ、バーを再表示します。

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

    [super viewWillDisappear:animated];
}

3
+1、通常、モーダルダイアログを押したときにナビゲーションバーを表示したくない。
ジョアン・ポルテラ

17

表示されている各ビューのviewWillAppearデリゲートにコードを配置します。

これを非表示にする必要がある場合:

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

あなたがそれを示す必要がある場所では、このように:

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

リー、これで問題が解決した場合は、パブロを「解決策」の答えとしてマークしてください。
Rog、

2
これに関する唯一の問題は、あるビューから次のビューにナビゲートすると、ナビゲーションバーが「飛び出して」ビューに表示されることです。最初のビューにナビゲーションバーがないようにすることは可能ですか?2番目のビューが所定の位置にスライドすると、ポップせずにナビゲーションバーが表示されますか?
ヘニング

2
@henning NavBarを期待どおりにスライドイン/スライドアウトするには、setNavigationBarHidden:animated:を使用する必要があります。以下のAlan Rogersの回答を参照してください(実際には「解決策」としてマークされているはずです)。
Nick Forge

2
この答えは少し間違っています(viewWill / DidAppear)がsuperを呼び出す必要があります。また、すべてのビューコントローラーに追加する必要がないソリューションについては、以下の私の回答を参照してください。
アランロジャース

15

現在受け入れられている回答は、質問で説明されている意図された動作と一致しません。質問では、ナビゲーションバーをルートビューコントローラーで非表示にして他の場所に表示するように求めていますが、受け入れられた回答は特定のビューコントローラーでナビゲーションバーを非表示にします。最初のビューコントローラーの別のインスタンスがスタックにプッシュされるとどうなりますか?ルートビューコントローラーを見ていなくても、ナビゲーションバーは非表示になります。

代わりに、@ Chad M.のを使用する戦略は適切です。UINavigationControllerDelegateここに、より完全なソリューションを示します。手順:

  1. サブクラス UINavigationController
  2. -navigationController:willShowViewController:animatedルートビューコントローラを表示しているかどうかに基づいてナビゲーションバーを表示または非表示にするメソッドを実装します
  3. 初期化メソッドをオーバーライドして、UINavigationControllerサブクラスを独自のデリゲートとして設定します

このソリューションの完全なコードは、このGistにあります。ここにnavigationController:willShowViewController:animated実装があります:

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

2
これは、承認された答えよりも適切な答えです
Pavel Gurov

14

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

!=自己をチェックする理由を説明していただけますか?
Kitson

2
@ Kitson、user486646の回答を確認してください。 他の回答に加えなければならないわずかな調整の1つは、ナビゲーションアイテムがプッシュされているためにバーが非表示になっている場合は、viewWillDisappearのバーを再表示することだけです。これは、ビューが他の理由で消えることがあるためです。私はバーを再表示するので、このビューは、もはや最上位のビューでない場合
ユージンBraginets

これを使用するnavcontroller.navagationBarHiddenと、ナビゲーションコントローラ全体が破損するようです(前後にスワイプしないでください)。動作させるためにnavigationController?.navigationBar.hidden代わりに使用しました。スワイプは引き続き機能し、スタックビューまたは何かの中にあるように見えるため、空のスペースは残りません
サイレン

8

@ chad-mの回答に私のクレジットを与えてください。

これがSwiftバージョンです:

  1. 新しいファイルを作成する 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. StoryBoardのUINavigationControllerのクラスをMyNavigationControllerに設定します MyNavigationController

chad-mの答えと私の違い:

  1. UINavigationControllerから継承するので、rootViewControllerを汚染することはありません。

  2. ではself.viewControllers.firstなくを使用するhomeViewControllerので、1つのStoryBoard内の100個のUINavigationControllersに対してこれを100回行うことはありません。


これが最もきれいな答えだと思います。ありがとう
DaSilva

6

複数の試行の後、ここで私はそれを私が望んだもののために機能させた方法です。これは私が試していたものです。-画像付きのビューがあります。画像を全画面表示にしたかったのです。-私はtabBarを備えたナビゲーションコントローラも持っています。だから私もそれを隠す必要があります。-また、私の主な要件は、単に隠すだけではなく、見せたり隠したりするときにフェード効果を持たせることでもありました。

これは私がそれを機能させた方法です。

ステップ1-画像があり、ユーザーはその画像を1回タップします。そのジェスチャーをキャプチャして、新しいにプッシュします。imageViewControllerそのimageViewControllerフルスクリーンイメージが必要です。

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

ステップ2-以下のすべてのステップはImageViewControllerにあります

ステップ2.1-ViewDidLoadで、navBarを表示します

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

ステップ2.2-でviewDidAppear、タイマータスクに遅延を設定します(1秒の遅延に設定しています)。そして、遅延の後、フェージング効果を追加します。フェージングを使用するためにアルファを使用しています。

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

ステップviewWillAppear2.3-の下で、画像にシングルタップジェスチャーを追加し、navBarを半透明にします。

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

ステップ3-最後にviewWillDisappear、すべてのものを元に戻してください

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

4

受け入れられた回答に@fabbがコメントしたため高速バックスワイプでまだ問題が解決しない場合は、バグをキャンセルしました。

以下に示すようviewDidLayoutSubviewsに加えて、をオーバーライドすることでこれを修正することができviewWillAppear/viewWillDisappearます:

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

私の場合、ルートビューコントローラー(navが非表示になっている)とプッシュされたビューコントローラー(navが表示されている)のステータスバーのスタイル(暗いと明るいなど)が異なるためです。バックスワイプを開始してビューコントローラーをポップすると、ステータスバーの色のアニメーションが追加されます。インタラクティブなポップをキャンセルするために指を離すと、ステータスバーのアニメーションが終了していない間、ナビゲーションバーは永久に消えてしまいます。

ただし、両方のビューコントローラーのステータスバーのスタイルが同じ場合、このバグは発生しません。


1

コントローラーでナビゲーションバーを完全に非表示にする場合は、ルートコントローラーで次のようにすることで、よりクリーンなソリューションを実現できます。

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

コントローラーで子ビューを押すと、ナビゲーションバーは非表示のままになります。子にのみ表示する場合it(self.navigationController.navigationBarHidden=NO;)は、viewWillAppearコールバックに表示するためのコードを追加し、同様に非表示にするためのコードを追加しますviewWillDisappear


0

最も簡単な実装は、各ビューコントローラに、そのviewWillAppear:animated:メソッドでナビゲーションバーを非表示にするかどうかを指定させることです。同じ方法がツールバーの非表示/表示にも有効です。

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

実際、私の提案はツールバーにのみ意味があります。それは、一致する呼び出しを表示せずにナビゲーションバーを非表示にすると、ユーザーが現在のビューから戻ってナビゲートできなくなるためです。
SteveCaine

0

最初のページでのみナビゲーションバーを非表示にするには、ストーリーボードを使用することもできます。ストーリーボードで、ナビゲーションコントローラーの[シーン]-> [ナビゲーションバー]に移動します。そして、属性インスペクタから「非表示」プロパティを選択します。これにより、最初のビューコントローラーから始まり、必要なビューコントローラーに表示されるまで、ナビゲーションバーが非表示になります。

ナビゲーションバーは、ViewControllerのViewWillAppearコールバックで可視に戻すように設定できます。

-(void)viewWillAppear:(BOOL)animated {

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

0

スウィフト4:

ビューコントローラーで、ナビゲーションバーを非表示にします。

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

-1

このコードをViewControllerに実装することで、この効果を得ることができます。実際には、そのコントローラーが起動されたときに、navigationBarを非表示にします。

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

そして、ユーザーがそのページを離れるときにナビゲーションバーを再表示しますこれはviewWillDisappearです

- (void)viewWillDisappear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:NO animated:YES];
    [super viewWillDisappear:animated];
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.