IOS7 中的 UINavigationBar/状态栏问题
Posted
技术标签:
【中文标题】IOS7 中的 UINavigationBar/状态栏问题【英文标题】:UINavigationBar/Status Bar issue in IOS7 【发布时间】:2013-09-27 17:09:43 【问题描述】:最终编辑
(而不是有一个过长的问题需要进行最终编辑以进行澄清,如果需要,请查看其他编辑)。
控制器设置
我有一个设置如下的应用程序:
InitialViewController(ECSlidingViewController 的子类)
主导航控制器(UINavigationController
的子类)
主主视图控制器(UIViewController
的子类)
在 initialViewController 的 viewDidLoad
中,我将主导航控制器加载到主视图控制器作为其根。
self.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MainNavVC"];
问题
在第一次加载应用程序时,状态栏和导航栏是分开的。
这是想要的效果。
不过,我随后会使用标准方法加载一个模态视图控制器并关闭它:
[self performSegueWithIdentifier:@"LoadSelectOpponentVC" sender:self];
然后关闭:
[self dismissViewControllerAnimated:YES completion:nil];
这反过来会导致主导航控制器(持有主视图控制器)不正确地显示状态栏并重叠:
测试
-
plist 设置设置为 YES -
View controller-based status bar appearance
我已尝试将edgesForExtendedLayout
设置为相关的无,但没有更改。
记录
我已尝试注销一些框架以查看问题所在:
首次加载时:
主导航 VC - 视图框架 - 0, 0, 320, 480
Main Nav VC - Nav Bar Frame - 0, 0, 320, 44
Initial VC - View Frame - 0, 0, 320, 480
Home VC - View Frame - 0, 0, 320, 480 -- viewDidLoad Home VC
Home VC - View Frame - 0, 64, 320, 416 -- viewWillAppear Home VC
--- After Modal is opened/closed ----
Home VC - View Frame - 0, 64, 320, 416 -- viewWillAppear Home VC
Main Nav VC - View Frame - 0, 0, 320, 480 -- viewWillAppear Main Nav
Main Nav VC - Nav Bar Frame - 0, 20, 320, 44 -- viewWillAppear Main Nav
Home VC - View Frame - 0, 44, 320, 436 -- viewDidAppear Home VC
【问题讨论】:
“在顶部栏下扩展”只会影响您的视图与导航栏的关系。 您是否尝试过将导航栏的框架向下移动到状态栏的高度? 这应该在哪里完成呢?你能提供一个答案吗? 这里有同样的问题...正在寻找解决方案。 您找到解决方案了吗?对我来说同样的问题,当我为第一个控制器打印导航栏框架时,它会打印 (x,y)->(0,20),然后当我推动视图控制器时,它会打印 (x,y)->(0,0)。怎么变成0了? 【参考方案1】:您是否尝试过 Apple 关于“防止状态栏覆盖您的视图”的建议:https://developer.apple.com/library/content/qa/qa1797/_index.html
你有没有看过“UIBarPositioningDelegate”:https://developer.apple.com/documentation/uikit/uibarpositioningdelegate
【讨论】:
此参考说明“使用不透明 UINavigationController 或 UITabBarController 的应用程序会自动将其内容保留在状态栏下方。”但这显然不是我的示例/问题。我也尝试将栏定位设置为顶部和顶部附加无济于事。 我使用了“防止状态栏覆盖您的视图”中介绍的方法,该方法为顶部布局指南设置了垂直空间约束,并且我放在视图上的 UINavigationBar 放置在状态栏。通过将 UINavigationBar 与视图顶部的 20 像素垂直空间固定在一起,我得到了相同的结果。 确保为整个视图控制器正确设置自动布局。苹果文档只是说修复第一个。我只在顶部布局指南和顶部视图之间应用了约束,没有其他约束,它不起作用。但是一旦 Id 至少为 viewcontroller.view 下面的所有视图添加了约束并清除了 IB 中的所有布局警告 UIBarPositioningDelegate 就像一个魅力!只需将您的视图控制器设置为 UIBarPositioningDelegate 并将其分配为栏的代表。然后将此方法添加到您的视图控制器(仅在 ios7+ 中可用): - (UIBarPosition)positionForBar:(idassign it as the bar's delegate
。状态栏有委托吗?还是你的意思是 UINavigationBar?【参考方案2】:
在 iOS 7.0 中,UIViewController
默认以这种方式工作。如果您在 UINavigationController
中使用 UIViewController 并且 navigationBar
可见,则视图将全屏显示。
如果导航栏可见,请执行以下操作。 ==>
self.edgesForExtendedLayout = UIRectEdgeNone
如果 navigationBar 被隐藏,请执行以下操作。 ==>
通过移动 20 个点来调整所有 UIView
元素
如果你使用Interface builder,你可以使用iOS6/7的deltas:首先“view as iOS 6.0”,然后设置一个delta为“20”来实现iOS 7中的+20偏移
【讨论】:
edgeForExtendedLayout 会影响视图控制器与状态栏的实际显示方式,内容是否会放在下方等。我已经提出了我已经尝试过的问题。 @SunilAdhyaru "首先,"查看为 iOS 6.0",然后设置 delta 为 "20" 以实现 iOS 7 中的 +20 偏移量" 你能解释一下吗? 当然。基本上你必须将视图设置为 iOS 6.0 而不是 7.0。您可以在Interface Builder的“Interface Builder Document”项中看到它。【参考方案3】:我很惊讶还没有人找到正确的答案。 UIBarPositioningDelegate 就像一个魅力!只需将您的视图控制器设置为 UIBarPositioningDelegate 并将其分配为栏的代表。将条形图放置在距离视图顶部 20 像素的位置。然后将此方法添加到您的视图控制器(仅在 iOS7+ 中可用):
- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar
return UIBarPositionTopAttached;
【讨论】:
不,由于时间限制,我们不得不采取不同的方法。我们将 SO 问题保留为开放式,因为所有答案都与该问题相关且解决方法。谢谢 你能详细说明一下吗? AFAIK 当导航栏由导航控制器管理时,您无法设置导航栏的委托。 此解决方案在向 UIViewController 添加自定义导航栏时有效。对于 UINavigationController,您需要创建 UINavigationController 的子类并将该子类定义为 UINavigationBarDelegate(符合 UIBarPositioningDelegate),类似于:***.com/a/7453933/485895。只需添加我的答案中提到的 positionForBar: 方法即可解决相关问题,但您可以看到这种子类方法也为您提供了其他机会。【参考方案4】:我在“汉堡”菜单按钮上遇到了类似的问题,该按钮将主视图控制器滑过并在侧面有一个菜单视图控制器。我发现菜单视图控制器的导航栏不知道状态栏是否显示。我通过在状态栏显示和隐藏然后执行时发布通知来修复它
[self.navigationController setNavigationBarHidden:YES/NO animated:NO];
在菜单的视图控制器中。
【讨论】:
【参考方案5】:我使用这篇文章的答案解决了这样一个问题:iOS 7 | Navigation bar / Toolbar buttons very close to status bar
使用自动布局时,您应该忽略设置新框架。您应该为 iOS 7 的 TopBar 添加一个等于 20 的顶部空间约束。
【讨论】:
我已经尝试解决这个问题,但没有运气。您能否提供一个代码示例来说明您是如何设置 AutoLayout 的,或者您是否参加过 IB 比赛? 1.在代码中添加 Bar Top Space Constraint (Vertical Space - Navigation Bar - View) 的出口。 2.将工具栏的委托设置为相应的VC。 3. 添加上述url中指定的de delegate方法。 4.在viewWillAppear中添加这个> if (IS_IOS_7) self.navBarTopSpaceConstraint.constant = 20; 我还不能测试这个,我会尽快解决这个问题并更新 如果您无法测试(欣赏)某人的帮助,为什么还要请人帮助您? 我不得不使用不同的方法,因为我无法解决这个问题,我将在今天晚些时候重新打开项目并尝试让它工作。我相信问题在于第三方幻灯片菜单的工作方式,因为这也被报告给了他们并且他们无法解决。但该问题确实为其他有此问题的人提供了大量信息,以帮助他们尝试解决问题。【参考方案6】:您是否尝试将以下代码添加到您的 viewDidLoad
方法中:
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
Apple 迁移到 iOS 7 doumentation.
中很快解释了这一点【讨论】:
不要在帖子中包含签名。 是的,我已经尝试将它添加到我的视图控制器 viewDidLoad 和我的导航控制器子类 viewDidLoad 但没有改变【参考方案7】:我已经详细回答了这个问题in this answer to a similar question。简短的回答是:无法从 iOS 6 及更早版本中获得您习惯的自动状态栏布局行为。您必须围绕它进行设计,或者找到一种模拟旧样式的方法(我介绍了这两种方法)。
我强烈建议您不要对导航栏框架进行手动调整。让 UINavigationController 自己处理。很可能,您的问题是导航控制器的视图框架不等于 UIScreen 的边界。
【讨论】:
谢谢,我已经通过进一步的编辑更新了这个问题。我发现的是导航栏的框架变化。最初它加载为 0,20 偏移量,然后更改为 0,0。在应用商店中检查新应用时,它们的布局为 0,20。有没有简单的方法可以做到这一点。理想情况下,我不希望每次导航栏/其他视图越界时都必须对其进行动画处理 您是否在模态视图可见时隐藏状态栏? NIB 中 UINavigationController 视图(不是导航栏)的初始框架是什么? 您是在代码中还是在您的NIB 中直接使用UINavgationBar?如果是,为什么? 导航控制器的视图框架始终保持不变。导航视图框架:0, 0, 320, 480。我没有直接使用导航栏,它是从导航控制器使用的【参考方案8】:我知道您将 ViewController 作为主 VC。但是如果有人在使用 UITableviewController 并且遇到同样的问题,这段代码可以解决问题:
self.tableView.contentInset = UIEdgeInsetsMake(20.0f, 0.0f, 0.0f, 0.0f);
【讨论】:
【参考方案9】:解决这个问题其实很简单。它涉及操作 UINavigationBar 的 center.y
值,这是 UIKit 原生使用的,以便将 UINavigationBar 调整到状态栏的高度。为简单起见,我将 UINavigationBar 子类化并执行了以下操作:
@implementation MyNavigationBar
- (void) setCenter:(CGPoint)center
// Anything less than or equal to 22 is something we don't want (below SB height)
if(center.y > 22) [super setCenter:center];
@end
【讨论】:
【参考方案10】:是的,有同样的问题。遵循所有步骤,但没有变化。
通过确保为整个屏幕正确设置 AutoLayout 而不仅仅是在
中指定的顶视图/工具栏来使其工作“防止状态栏覆盖您的视图”:https://developer.apple.com/library/ios/qa/qa1797/_index.html
至少对于主 Viewcontroller.view 下方的所有视图。
【讨论】:
【参考方案11】:有一种内置方法可以做到这一点。 与 Joel Cave 的回答相同,但详细说明:
使您的导航栏的 Y 原点为 20 点。
然后在.h文件中:
@interface XYZViewController : UIViewController <UIBarPositioningDelegate>
在.m文件中:
- (void)viewDidLoad
[super viewDidLoad];
self.navigationBar.delegate = self;
- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar
return UIBarPositionTopAttached;
【讨论】:
我的视图控制器没有名为 navigationBar 的属性。 你可以用这个访问它,但它并没有解决问题 self.navigationController.navigationBar.delegate = self;如果你成功地解决了这个问题,请告诉我。这让我抓狂> 首先header的delegate类型是对我来说,解决方案是将导航栏移至 20 点
【讨论】:
【参考方案13】:我参加聚会有点太晚了,但是由于我遇到了同样的问题并且这是搜索中出现的第一个结果,我想我的回答可以帮助其他人:)
我通过实施解决了这个问题
- (BOOL)shouldAutorotate
return NO;
在呈现模式的视图控制器中。
【讨论】:
【参考方案14】:试试吧,所有的导航栏应该是半透明的都是禁用的。
[self.navigationController.navigationBar setTranslucent:NO];
如果您使用情节提要设计视图,则可以使用 XCode 解决问题。选择 NavigationBar 小部件并取消选中“半透明”。
【讨论】:
以上是关于IOS7 中的 UINavigationBar/状态栏问题的主要内容,如果未能解决你的问题,请参考以下文章
iOS7如何绘制透明的UIToolbar或UINavigationBar
如何在 iOS7 中设置 UINavigationBar? [复制]
一段时间后,ios7 UINavigationBar 在状态栏下停止扩展
iOS7GM UINavigationBar 外观 setBackgroundImage:forBarMetrics:在 UIPopoverController 中不起作用