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

我有下面的代码隐藏和显示导航栏。 当第一个视图加载时隐藏,当“子”被调用时隐藏。 麻烦的是,我找不到事件/行动,当他们回到根视图时触发它再次隐藏….

我有一个“testing”button在手动执行动作的根页面,但它不是很漂亮,我希望它是自动的。

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

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

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

这将导致导航栏从左侧(与下一个视图一起)animation,当您按下后退button时,将下一个UIViewController放到堆栈上,并向左移动(与旧视图一起) UINavigationBar

请注意,这些不是委托方法,你是重写UIViewController的这些方法的实现,根据文档,你必须调用超实现在你的实现中的某处

我发现的另一种方法是设置NavigationController的委托,并在navigationController:willShowViewController:animated:设置NavigationBarHiddennavigationController:willShowViewController:animated:

 - (void)navigationController:(UINavigationController *)navController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{ // hide the nav bar if going home if (viewController == homeViewController) [navController setNavigationBarHidden:YES animated:animated]; else [navController setNavigationBarHidden:NO animated:animated];} 

简单的方法可以在一个地方自定义每个ViewController的行为。

我会把代码放在每个view上的viewWillAppear委托中:

像这样你需要隐藏它:

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

像这样你需要显示它:

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

我必须在其他答案上做一点小小的调整,只有在viewWillDisappear中才能取消隐藏栏,如果它正在消失的原因是由于导航条被按下了。 这是因为视图可能因其他原因而消失。

所以如果这个观点不再是最顶层的观点,我只能取消吧:

 - (void) viewWillDisappear:(BOOL)animated { if (self.navigationController.topViewController != self) { [self.navigationController setNavigationBarHidden:NO animated:animated]; } [super viewWillDisappear: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) } 

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

相反,@Chad M.使用UINavigationControllerDelegate的策略是很好的,这是一个更完整的解决scheme。 脚步:

  1. 子类UINavigationController
  2. 实现-navigationController:willShowViewController:animated方法根据显示或隐藏导航栏是否显示根视图控制器
  3. 重写初始化方法以将UINavigationController子类设置为其自己的委托

这个解决scheme的完整代码可以在这个Gist中find。 这里是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中,显示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]; } 

如果有人仍然在快速backswipe取消了错误的错误 @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) } 

在我的情况,我注意到,这是因为根视图控制器(其中导航隐藏)和推视图控制器(导航显示) 具有不同的状态栏样式 (如黑暗和光明)。 当你开始backswipepopup视图控制器,将会有额外的状态栏颜色animation。 如果松开手指以取消交互式popup窗口, 而状态栏animation未完成 ,导航栏将永远消失!

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

如果你想要将导航条完全隐藏在控制器中,那么更简洁的解决scheme就是在根控制器中有如下的东西:

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

当您在控制器中按下子视图时,导航栏将保持隐藏状态; 如果你只想在子it(self.navigationController.navigationBarHidden=NO;)显示it(self.navigationController.navigationBarHidden=NO;) ,你将在viewWillAppearcallback中添加用于显示it(self.navigationController.navigationBarHidden=NO;)的代码it(self.navigationController.navigationBarHidden=NO;) ,类似的,隐藏在it(self.navigationController.navigationBarHidden=NO;)上的代码将会it(self.navigationController.navigationBarHidden=NO;)

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

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

通过在你的ViewController中实现这个代码,你可以得到这个效果其实诀窍是,当Controller启动时隐藏导航栏

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

简单的Swift 3兼容的答案:使用segue并以模态方式呈现。 这符合Apple文档。 https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html

示例:login页面控制器 – >导航控制器 – >创build新的帐户控制器(通过后退button链接回login页通过segue模态提出)

当链接回你不希望导航栏出现的另一个页面时,在这个页面上创build一个segue,在这个例子中,将它附加到后退button并拖到login页面,但是selectPresent Modally。 这一切都可以从Main.storyboard完成。

不需要编码!

仅在第一页隐藏导航栏也可以通过故事板来实现。 在故事板上,转到导航控制器场景 – >导航栏 。 并从“ 属性”检查器中select“ 隐藏 ”属性。 这将隐藏导航栏从第一个viewcontroller开始,直到它为所需的视图控制器可见。

在ViewController的ViewWillAppearcallback中,导航栏可以重新设置为可见。

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