下面的代码隐藏并显示了导航栏。它在第一个视图加载时被隐藏,然后在“子”被调用时被隐藏。问题是,当他们回到根视图....时,我找不到触发它再次隐藏的事件/动作

我在根页面上有一个“测试”按钮,手动执行操作,但它并不漂亮,我希望它是自动的。

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

我将把代码放在viewWillAppear委托中显示每个视图:

就像你需要隐藏它的地方:

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

就像这样,你需要展示它:

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

如果你想把导航栏完全隐藏在控制器中,一个更干净的解决方案是,在根控制器中,有这样的东西:

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

当你在控制器中推送子视图时,导航栏将保持隐藏状态;如果你想只在子对象中显示它,你将在viewWillAppear回调中添加用于显示它的代码(self.navigationController.navigationBarHidden=NO;),类似地,在viewWillDisappear中隐藏它的代码


我发现的最好的解决方案是在第一个视图控制器中执行以下操作。

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的实现。


我不得不对其他答案做出的一个轻微调整是,只有在viewWillDisappear中取消隐藏条,如果它消失的原因是由于导航项被推到它上面。这是因为视图可能因其他原因而消失。

所以我只在这个视图不再是最顶层视图时才取消隐藏条:

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

    [super viewWillDisappear:animated];
}

我发现的另一种方法是为NavigationController设置一个委托:

navigationController.delegate = self;

然后使用setNavigationBarHidden in navigationController: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定制行为的简单方法。


最简单的实现可能是让每个视图控制器在viewWillAppear:animated:方法中指定它的导航栏是否隐藏。同样的方法也适用于隐藏/显示工具栏:

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

经过多次试验,这里是我如何让它为我想要的工作。 这就是我一直在尝试的。 -我有一个图像视图。我想把图片全屏显示。 -我有一个导航控制器与选项卡太。所以我也要把它藏起来。 此外,我的主要要求不仅仅是隐藏,而且在显示和隐藏时也要有淡出效果。

这就是我让它工作的方法。

步骤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秒延迟)。并且在延迟之后,添加渐褪色效果。我用alpha来进行衰落。

- (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手势到图像,并使导航栏半透明。

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

第三步-最后在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。的策略使用UINavigationControllerDelegate是一个很好的策略,这里有一个更完整的解决方案。步骤:

子类UINavigationController 实现-navigationController:willShowViewController:animated方法,根据导航栏是否显示根视图控制器来显示或隐藏导航栏 重写初始化方法,将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];
    }
}

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

如果有人仍然对@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是显示的)有不同的状态栏风格(例如暗和亮)。当你开始向后滑动以弹出视图控制器时,会有额外的状态栏颜色动画。如果你为了取消交互式弹出而松开手指,而状态栏动画还没有完成,导航栏就永远消失了!

但是,如果两个视图控制器的状态栏样式相同,则不会出现此错误。


通过在你的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];
}

只在第一页隐藏导航栏也可以通过故事板实现。在故事板上,进入导航控制器场景->导航栏。从属性检查器中选择“Hidden”属性。这将从第一个视图控制器开始隐藏导航条,直到所需的视图控制器可见为止。

导航栏可以在ViewController的ViewWillAppear回调中设置为可见。

-(void)viewWillAppear:(BOOL)animated {

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

斯威夫特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)
}

我相信@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)
        }
    }

}

在StoryBoard中将UINavigationController的类设置为MyNavigationController 就是这样!

chad-m的回答和我的不同之处在于:

继承自UINavigationController,所以你不会污染你的rootViewController。 使用self.viewControllers.first而不是homeViewController,这样你就不会为你的100个UINavigationControllers在一个StoryBoard中做100次。