iPhone仅在第一页上隐藏导航栏

时间:2009-05-10 16:09:25

标签: ios uinavigationcontroller hide

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

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

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

14 个答案:

答案 0 :(得分:1000)

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

<强>目标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的实现

答案 1 :(得分:43)

我找到的另一种方法是为NavigationController设置委托:

navigationController.delegate = self;

并在setNavigationBarHidden

中使用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的行为。

答案 2 :(得分:17)

我必须对其他答案进行一次轻微的调整,只是取消隐藏在viewWillDisappear中的栏,如果它消失的原因是由于推送导航项目。这是因为视图可能因其他原因而消失。

因此,如果此视图不再是最顶层的视图,我只会取消隐藏栏:

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

    [super viewWillDisappear:animated];
}

答案 3 :(得分:16)

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

像这样你需要隐藏它:

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

像这样你需要展示它:

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

答案 4 :(得分: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)
}

答案 5 :(得分:12)

当前接受的答案与问题中描述的预期行为不符。该问题要求导航栏隐藏在根视图控制器上,但在其他任何地方都可见,但接受的答案会隐藏特定视图控制器上的导航栏。当第一个视图控制器的另一个实例被推入堆栈时会发生什么?即使我们没有查看根视图控制器,它也会隐藏导航栏。

相反,使用UINavigationControllerDelegate的@Chad M. strategy是一个很好的解决方案,这是一个更完整的解决方案。步骤进行:

  1. 子类UINavigationController
  2. 实施-navigationController:willShowViewController:animated方法,根据是否显示根视图控制器来显示或隐藏导航栏
  3. 重写初始化方法,将UINavigationController子类设置为自己的委托
  4. 此解决方案的完整代码可在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];
        }
    }
    

答案 6 :(得分:6)

经过多次试验,我是如何让它按照我想要的方式工作的。 这就是我的尝试。 - 我有一个图像的视图。我想让图像全屏显示。 - 我也有一个带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中,显示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秒延迟)。并且在延迟之后,添加褪色效果。我使用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手势添加到图像并使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];
}

答案 7 :(得分:4)

感谢@ 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 就是这样!

乍得的答案和我的答案之间的区别:

  1. 继承自UINavigationController,因此您不会污染rootViewController。

  2. 使用self.viewControllers.first而不是homeViewController,因此您不会在1个StoryBoard中为100个UINavigationController进行100次操作。

答案 8 :(得分:3)

如果@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)
}

在我的情况下,我注意到这是因为根视图控制器(导航被隐藏)和推出的视图控制器(显示导航)具有不同的状态栏样式(例如暗和亮)。在您启动反向扫描以弹出视图控制器的那一刻,将会有其他状态栏颜色动画。如果您松开手指以取消交互式弹出,状态栏动画未完成,导航栏将永远消失!

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

答案 9 :(得分:1)

如果你想要的是完全隐藏控制器中的导航栏,一个更清洁的解决方案是在根控制器中有类似的东西:

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

在控制器中推送子视图时,导航栏将保持隐藏状态;如果您想在子项中显示它,您将添加用于在it(self.navigationController.navigationBarHidden=NO;)回调中显示viewWillAppear的代码,以及用于将其隐藏在viewWillDisappear上的代码

答案 10 :(得分:0)

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

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

答案 11 :(得分:0)

仅在第一页上隐藏导航栏也可以通过故事板实现。在故事板上,转到导航控制器场景 - >导航栏。然后选择隐藏&#39;来自属性检查器的属性。这将隐藏从第一个viewcontroller开始的导航栏,直到它对于所需的viewcontroller可见。

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

-(void)viewWillAppear:(BOOL)animated {

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

答案 12 :(得分:0)

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

答案 13 :(得分:-1)

通过在ViewController中实现此代码,您可以获得此效果  实际上诀窍是,在启动Controller时隐藏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];
}