在根页面上有一个“测试”按钮可以手动执行该操作,但它不够美观,我希望它自动执行。
-(void)hideBar
{
self.navController.navigationBarHidden = YES;
}
-(void)showBar
{
self.navController.navigationBarHidden = NO;
}
-(void)hideBar
{
self.navController.navigationBarHidden = YES;
}
-(void)showBar
{
self.navController.navigationBarHidden = NO;
}
我发现最好的解决方案是在第一个视图控制器中执行以下操作。
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];
}
Swift
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
的行为。
在其他答案上我需要稍微调整一下,只有在导航项被推到栏上时,才在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];
}
目前被接受的答案与问题中描述的意图不符。问题要求在根视图控制器上隐藏导航栏,但在其他所有地方可见,但被接受的答案在特定的视图控制器上隐藏了导航栏。当第一个视图控制器的另一个实例被推入堆栈时会发生什么?它将隐藏导航栏,即使我们没有查看根视图控制器。
相反,@Chad M.使用UINavigationControllerDelegate
的策略是不错的,这里是一个更完整的解决方案。步骤:
UINavigationController
-navigationController:willShowViewController:animated
方法,以根据是否显示根视图控制器来显示或隐藏导航栏这个解决方案的完整代码可以在此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)
}
navcontroller.navagationBarHidden
,它会破坏整个导航控制器(无法左右滑动)。为了使其正常工作,我改用了 navigationController?.navigationBar.hidden
。左右滑动仍然有效,并且不会留下空白空间,因为它似乎在堆栈视图中或其他地方。 - Allison将我的信用归功于@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。
使用self.viewControllers.first
而不是homeViewController
,这样就不需要在1个Storyboard中的100个UINavigationControllers上执行此操作100次。
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];
}
第二步 - 下面所有的步骤都在ImageViewController中进行
第二步.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.
}
viewWillAppear
下,向图像添加单击手势,并使导航栏半透明。- (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];
}
如果仍然有人遇到@fabb在接受的答案中提到的快速后滑取消bug问题,我可以通过覆盖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)
}
@implementation MainViewController
- (void)viewDidLoad {
self.navigationController.navigationBarHidden=YES;
//...extra code on view load
}
viewWillAppear
回调中添加用于显示的代码(self.navigationController.navigationBarHidden=NO;)
,同样,在viewWillDisappear
上添加隐藏它的代码。
animated=YES
导致的。我知道使用animated=NO
看起来很丑陋,但似乎当隐藏导航栏的动画还未完成时,再次显示它的动画将被忽略。目前还没有解决办法。 - fabb