导航栏的显示/隐藏

163
我有一个应用程序,其中包含2个导航栏按钮。我想在用户双击屏幕时隐藏和显示此导航栏。
最初,导航栏应该被隐藏。当用户双击屏幕时,导航栏应该带有动画效果出现,就像在iPhone的照片库中看到的那样。
我应该如何实现这个功能?欢迎提供建议。
11个回答

392

这不是可以用几行代码解决的问题,但这是一种可能适用于你的方法。

隐藏导航栏:

[[self navigationController] setNavigationBarHidden:YES animated:YES];
展示它的方法:
[[self navigationController] setNavigationBarHidden:NO animated:YES];

该方法的文档在此处可用

要监听“双击”或双击操作,请子类化UIView,并将该子类的一个实例作为您视图控制器的view属性。

在视图子类中,重写其-touchesEnded:withEvent:方法,并通过测量两个连续点击之间的时间来计算在一段时间内获得的触摸次数,也许可以使用CACurrentMediaTime()。或测试从[touch tapCount]获取的结果。

如果您获得了两个点击,则您的子类视图会发出一个由您的视图控制器注册以侦听的NSNotification

当您的视图控制器收到通知时,它将触发一个选择器,根据导航栏的当前可见状态(通过读取导航栏的isHidden属性访问)使用上述代码隐藏或显示导航栏。

编辑

在处理点击事件的部分可能在iOS 3.1之前有用。如今,UIGestureRecognizer类可能是处理双击的更好方法。

编辑2

隐藏导航栏的Swift方式是:

navigationController?.setNavigationBarHidden(true, animated: true)
展示它:
navigationController?.setNavigationBarHidden(false, animated: true)

如果这是用于照片查看器应用程序,隐藏导航栏会导致图像视图出现不愉快的跳动,我还没有找到如何防止它。3.2版本允许您使用UIGestureRecognizer进行双击操作,这是一种更加整洁的方法(目前仅适用于iPad)。 - Paul Lynch
1
有没有任何方法可以防止Paul提到的这种“跳跃”?我也遇到了完全相同的问题,但不知道是什么原因...我认为也许并不是没有人遇到过。 - Icky
为了防止出现“跳跃”,您需要在隐藏/显示导航栏后重置滚动视图的contentInset属性,就像jclee所提到的那样。即:self.scrollView.contentInset = UIEdgeInsetsZero - crafterm
我在我的视图中有一个表视图,但上述建议的方法实际上阻止了我选择表行...还有其他替代方案吗? - Pradeep Reddy Kypa
+1 “这不是可以用几行代码解决的问题……” ……然后呈现了几行代码来解决问题 XD - Will Von Ullrich
显示剩余3条评论

17

这段代码将会对您有所帮助。

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] 
initWithTarget:self action:@selector(showHideNavbar:)];
[self.view addGestureRecognizer:tapGesture];

-(void) showHideNavbar:(id) sender 
{ 
// write code to show/hide nav bar here 
// check if the Navigation Bar is shown
if (self.navigationController.navigationBar.hidden == NO)
{
// hide the Navigation Bar
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
// if Navigation Bar is already hidden
else if (self.navigationController.navigationBar.hidden == YES)
{
// Show the Navigation Bar
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
}

16
首先阅读iOS视图控制器编程指南中关于“采用全屏布局的导航视图”和自定义视图相同部分的内容。如果你想要做像Photos.app那样的东西,你可能正在使用滚动视图。注意导航栏会自动向你的滚动视图添加一个滚动内容插入来适应导航栏(和状态栏)的高度,所以在设置navigationBar的初始状态之后,在视图出现之前,你必须将scrollView的contentInset属性重置为零(UIEdgeInsetsZero)。
然后,如果你有一个单击事件来切换是否显示navigationBar和/或status bar,你需要在你的切换方法中执行两件事。第一件事似乎是在更改navigationBar隐藏属性之前保存scrollView的contentOffset属性,并在更改完成后恢复保存的值到contentOffset。第二件事是在更改navigationBarHidden属性之后再次将contentInset属性设置为UIEdgeInsetsZero。此外,如果你想要切换状态栏,你需要在更改navigationBar的状态之前更改它的状态。

1
非常感谢你关于contentOffset和contentInset的说明,你是真正的英雄。 - Altealice
我同意,你是真正的英雄!非常感谢。 - Gaetan

11

Swift 中尝试这样做:

navigationController?.isNavigationBarHidden = true  //Hide
navigationController?.isNavigationBarHidden = false //Show
或者
navigationController?.setNavigationBarHidden(true, animated: true) //Hide
navigationController?.setNavigationBarHidden(false, animated: true) //Show

7

这里有一个非常快速简单的解决方案:

self.navigationController.hidesBarsOnTap = YES;

这将在单击而非双击时起作用。即使推送或弹出当前视图控制器,它也会改变导航控制器的行为。
如果您只想为单个视图控制器设置行为,则可以在controller的viewWillAppear:和viewWillDisappear:操作中修改此行为。
这里是文档

7
隐藏导航栏:

要隐藏导航栏:

[self.navigationController setNavigationBarHidden:YES animated:YES];

显示导航栏:

[self.navigationController setNavigationBarHidden:NO animated:YES];

在iOS 7中,自动完成实际上支持该解决方案,而不是投票最高的解决方案。 - Alex Zavatone

5
一种方法是在属性检查器中取消勾选“显示导航栏”的工具栏可见性。希望这能帮助到某些人。

输入图像描述


2

In Swift 4.2 and Xcode 10

self.navigationController?.isNavigationBarHidden = true  //Hide
self.navigationController?.isNavigationBarHidden = false  //Show

如果您不想在第一个VC中仅显示导航栏,但您希望在第二个VC及以后的VC中显示,请在第一个VC中编写以下代码。"最初的回答"
在第一个VC中加入以下代码即可实现您的需求。
override func viewWillAppear(_ animated: Bool) {
    self.navigationController?.isNavigationBarHidden = true  //Hide
}

override func viewWillDisappear(_ animated: Bool) {
    self.navigationController?.isNavigationBarHidden = false  //Show
}

2

如果你想检测导航栏的状态是隐藏还是显示,你可以使用以下代码进行检测 -

if self.navigationController?.isNavigationBarHidden{
    print("Show navigation bar")
} else {
    print("hide navigation bar")
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接