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:(id)bar return UIBarPositionTopAttached; @JoelCave 我如何assign 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类型是,其次这并不能解决问题。【参考方案12】:

对我来说,解决方案是将导航栏移至 20 点

【讨论】:

【参考方案13】:

我参加聚会有点太晚了,但是由于我遇到了同样的问题并且这是搜索中出现的第一个结果,我想我的回答可以帮助其他人:)

我通过实施解决了这个问题

- (BOOL)shouldAutorotate

    return NO;

在呈现模式的视图控制器中。

【讨论】:

【参考方案14】:

试试吧,所有的导航栏应该是半透明的都是禁用的。

[self.navigationController.navigationBar setTranslucent:NO];

如果您使用情节提要设计视图,则可以使用 XCode 解决问题。选择 NavigationBar 小部件并取消选中“半透明”。

【讨论】:

以上是关于IOS7 中的 UINavigationBar/状态栏问题的主要内容,如果未能解决你的问题,请参考以下文章

iOS7如何绘制透明的UIToolbar或UINavigationBar

如何在 iOS7 中设置 UINavigationBar? [复制]

IOS7上UINavigationBar下的UIView

一段时间后,ios7 UINavigationBar 在状态栏下停止扩展

iOS7GM UINavigationBar 外观 setBackgroundImage:forBarMetrics:在 UIPopoverController 中不起作用

iOS7 UINavigationBar tintColor 在设置时更改为最大 .8