ナビゲーションバーを隠して表示する以下のコードがあります。最初のビューがロードされると非表示になり、次に「子」が呼び出されると非表示になります。問題は、ルートビューに戻ったときに再び非表示にするイベント/アクションが見つからないことです。
私は手動でアクションを実行するルートページに "test"ボタンを持っていますが、それはきれいではありません、そして私はそれが自動であることを望みます。
-(void)hideBar
{
self.navController.navigationBarHidden = YES;
}
-(void)showBar
{
self.navController.navigationBarHidden = NO;
}
私が見つけた最も良い解決策は最初の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の実装を呼ばなければなりません。
私が見つけたもう一つのアプローチは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
の動作をカスタマイズする簡単な方法。
私が他の答えにしなければならなかった1つのわずかな微調整はそれが消えている理由がそれに押されているナビゲーション項目のためである場合にだけviewWillDisappearでバーを隠すことです。これは他の理由でビューが消える可能性があるためです。
そのため、このビューが最上部のビューではなくなった場合にのみ、バーを表示します。
- (void) viewWillDisappear:(BOOL)animated
{
if (self.navigationController.topViewController != self)
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
[super viewWillDisappear:animated];
}
表示される各ビューのviewWillAppearデリゲートにコードを配置します。
あなたがそれを隠す必要があるところでこのように:
- (void)viewWillAppear:(BOOL)animated
{
[yourObject hideBar];
}
このように表示する必要がある場所は次のとおりです。
- (void)viewWillAppear:(BOOL)animated
{
[yourObject showBar];
}
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)
}
現在受け入れられている回答は、質問に記載されている意図した動作と一致しません。この質問では、ナビゲーションバーをルートView Controller上で隠すように要求しますが、それ以外の場所では表示されますが、受け入れられた答えは特定のView Controller上のナビゲーションバーを隠します。最初のView Controllerの別のインスタンスがスタックにプッシュされるとどうなりますか?ルートView Controllerを見ていなくても、ナビゲーションバーは非表示になります。
代わりに、UINavigationControllerDelegate
name__を使用する@Chad M.の strategy が良い方法です。ここで、より完全な解決策を示します。ステップ:
UINavigationController
name__-navigationController:willShowViewController:animated
メソッドを実装します。このソリューションの完全なコードは 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];
}
}
何度か試行した後、ここで私が望んでいたことがうまくいくようになりました。これは私が試みていたものです。 - 画像付きの景色があります。そして私はその画像をフルスクリーンにしたいと思った。 - 私も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];
}
@ chad-mの答えに私の信用を与えます。
これはSwiftバージョンです。
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)
}
}
}
Chad-mの答えと私の違い:
UINavigationControllerから継承するので、rootViewControllerを汚染することはありません。
homeViewController
ではなくself.viewControllers.first
を使用するので、1 StoryBoard内の100個のUINavigationControllerに対して100回これを実行することはありません。
@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のステータスバースタイルが同じ場合、このバグは発生しません。
ナビゲーションバーをコントローラ内で完全に非表示にしたい場合は、ルートコントローラ内に次のようなものを追加します。
@implementation MainViewController
- (void)viewDidLoad {
self.navigationController.navigationBarHidden=YES;
//...extra code on view load
}
コントローラで子ビューをプッシュしても、ナビゲーションバーは非表示のままになります。子の中だけに表示したい場合は、viewWillAppear
コールバックにit(self.navigationController.navigationBarHidden=NO;)
を表示するためのコードを追加し、同様にviewWillDisappear
にそれを隠すためのコードを追加します。
最も単純な実装は、各View Controllerに、ナビゲーションバーを非表示にするかどうかをviewWillAppear:animated:
メソッドで指定させることだけです。ツールバーの表示/非表示にも同じ方法が適しています。
- (void)viewWillAppear:(BOOL)animated {
[self.navigationController setToolbarHidden:YES/NO animated:animated];
[super viewWillAppear:animated];
}
最初のページにのみナビゲーションバーを隠すことは、ストーリーボードを通しても達成できます。絵コンテでは、後藤Navigation Controller Scene-> Navigation Bar。そしてAttributesインスペクタから 'Hidden'プロパティを選択してください。これはナビゲーションバーを最初のビューコントローラから始めて必要なビューコントローラに見えるようになるまで隠します。
ナビゲーションバーはViewControllerのViewWillAppearコールバックで表示に戻すことができます。
-(void)viewWillAppear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:YES animated:animated];
[super viewWillAppear:animated];
}
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)
}