web-dev-qa-db-ja.com

iPhoneはナビゲーションバーを最初のページにのみ隠す

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

私は手動でアクションを実行するルートページに "test"ボタンを持っていますが、それはきれいではありません、そして私はそれが自動であることを望みます。

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

私が見つけた最も良い解決策は最初のView Controllerで以下をすることです。

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の実装をオーバーライドしています、そしてあなたのドキュメントによればあなたの実装のどこかでsuperの実装を呼ばなければなりません

1003
Alan Rogers

私が見つけたもう一つのアプローチはNavigationControllerのためにデリゲートを設定することです:

navigationController.delegate = self;

navigationController:willShowViewController:animated:setNavigationBarHiddenを使用する

- (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の動作をカスタマイズする簡単な方法。

45
Chad M.

私が他の答えにしなければならなかった1つのわずかな微調整はそれが消えている理由がそれに押されているナビゲーション項目のためである場合にだけviewWillDisappearでバーを隠すことです。これは他の理由でビューが消える可能性があるためです。

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

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

    [super viewWillDisappear:animated];
}
17
user486646

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

あなたがそれを隠す必要があるところでこのように:

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

このように表示する必要がある場所は次のとおりです。

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

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

現在受け入れられている回答は、質問に記載されている意図した動作と一致しません。この質問では、ナビゲーションバーをルートView Controller上で隠すように要求しますが、それ以外の場所では表示されますが、受け入れられた答えは特定のView Controller上のナビゲーションバーを隠します。最初のView Controllerの別のインスタンスがスタックにプッシュされるとどうなりますか?ルートView Controllerを見ていなくても、ナビゲーションバーは非表示になります。

代わりに、UINavigationControllerDelegatename__を使用する@Chad M.の strategy が良い方法です。ここで、より完全な解決策を示します。ステップ:

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

このソリューションの完全なコードは this 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];
    }
}
12
hunteros

何度か試行した後、ここで私が望んでいたことがうまくいくようになりました。これは私が試みていたものです。 - 画像付きの景色があります。そして私はその画像をフルスクリーンにしたいと思った。 - 私もtabBar付きのナビゲーションコントローラを持っています。だから私もそれを隠す必要があります。 - また、私の主な要件は単に隠すだけではなく、見せたり隠したりしている間もフェード効果があることです。

これが私がそれを動かした方法です。

ステップ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で、ナビゲーションバーを表示する

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

ステップ2.3 - viewWillAppearの下で、画像にsingleTapジェスチャーを追加して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];
}
6
verma

@ 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. homeViewControllerではなくself.viewControllers.firstを使用するので、1 StoryBoard内の100個のUINavigationControllerに対して100回これを実行することはありません。

4
AI Lion

@fabbが受け入れた回答でコメントしたとして、誰かがまだ速いバックスワイプでキャンセルされたバグに問題を抱えている場合。

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

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が表示されている場所)ステータスバーのスタイルが異なる(暗いと明るいなど)が原因です。 View Controllerをポップするためにバックスワイプを開始すると、追加のステータスバーカラーアニメーションが表示されます。インタラクティブポップをキャンセルするために指を離すと、ステータスバーのアニメーションが終了していない間の場合、ナビゲーションバーは永久に消えてしまいます。

ただし、両方のView Controllerのステータスバースタイルが同じ場合、このバグは発生しません。

3
aunnnn

ナビゲーションバーをコントローラ内で完全に非表示にしたい場合は、ルートコントローラ内に次のようなものを追加します。

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

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

1
Alex

最も単純な実装は、各View Controllerに、ナビゲーションバーを非表示にするかどうかをviewWillAppear:animated:メソッドで指定させることだけです。ツールバーの表示/非表示にも同じ方法が適しています。

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

最初のページにのみナビゲーションバーを隠すことは、ストーリーボードを通しても達成できます。絵コンテでは、後藤Navigation Controller Scene-> Navigation Bar。そしてAttributesインスペクタから 'Hidden'プロパティを選択してください。これはナビゲーションバーを最初のビューコントローラから始めて必要なビューコントローラに見えるようになるまで隠します。

ナビゲーションバーはViewControllerのViewWillAppearコールバックで表示に戻すことができます。

-(void)viewWillAppear:(BOOL)animated {

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

Swift 4:

View Controllerで、ナビゲーションバーを非表示にします。

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)
}
0
John Riselvato