在 iOS 7 中,状态栏和导航栏出现在我的视图边界上

Posted

技术标签:

【中文标题】在 iOS 7 中,状态栏和导航栏出现在我的视图边界上【英文标题】:Status bar and navigation bar appear over my view's bounds in iOS 7 【发布时间】:2013-06-12 20:06:41 【问题描述】:

我最近下载了Xcode 5 DP 来测试我在 ios 7 中的应用程序。我注意到并确认的第一件事是,我的视图边界并不总是根据状态栏和导航栏调整大小。

viewDidLayoutSubviews 中,我打印视图的边界:

0, 0, 320, 568

这会导致我的内容显示在导航栏和状态栏下方。

我知道我可以通过获取主屏幕的高度,减去状态栏的高度和导航栏的高度来计算高度,但这似乎是不必要的额外工作。

我该如何解决这个问题?

更新:

我已经找到了解决这个特定问题的方法。将导航栏的 translucent 属性设置为 NO:

self.navigationController.navigationBar.translucent = NO;

这将修复视图在导航栏和状态栏下方的框架。

但是,当您希望导航栏为半透明时,我还没有找到解决方法。例如,在全屏查看照片时,我希望导航栏是半透明的,并且视图要框在它下面。这行得通,但是当我切换显示/隐藏导航栏时,我遇到了更奇怪的结果。第一个子视图(一个 UIScrollView)每次都会改变它的边界 y 原点。

【问题讨论】:

我在 xcode 5 DP 中也遇到了同样的问题 如果您能找到解决方案,请告诉我 在导航栏中查找 tint color 属性,您应该能够将蓝色更改为您想要的任何颜色。 有时我讨厌升级 ios,因为 Apple 从来没有给你机会让你的应用向后兼容。 如果问题与隐藏导航控制器顶部栏后状态栏下的视图有关,我会参考@Stunner ***.com/a/18976660/235206 的答案作为解决方案 【参考方案1】:

您可以通过在 iOS7 SDK 中实现一个名为 edgesForExtendedLayout 的新属性来实现这一点。请添加以下代码来实现这一点,

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

您需要在-(void)viewDidLoad 方法中添加上述内容。

iOS 7 对您如何布局和自定义 UI 的外观。视图控制器布局、色调的变化 颜色和字体会影响应用中的所有 UIKit 对象。在 此外,手势识别器 API 的增强功能让您更精细 对手势交互的粒度控制。

使用视图控制器

在 iOS 7 中,视图控制器使用全屏布局。同时, iOS 7 让您可以更精细地控制视图控制器的方式 阐述其观点。特别是全屏布局的概念 已改进为让视图控制器指定每个视图的布局 视野的边缘。

wantsFullScreenLayout 视图控制器属性在 iOS 7. 如果您当前指定wantsFullScreenLayout = NO,则视图 控制器可能会在意外的屏幕位置显示其内容 当它在 iOS 7 中运行时。

要调整视图控制器的视图布局方式,UIViewController 提供以下属性:

edgesForExtendedLayout

edgesForExtendedLayout 属性使用UIRectEdge 类型, 它指定了矩形的四个边中的每一个,除了 指定无和全部。使用edgesForExtendedLayout 指定哪个 无论条形半透明如何,都应扩展视图的边缘。经过 默认情况下,该属性的值为UIRectEdgeAll

extendedLayoutIncludesOpaqueBars

如果您的设计使用不透明条,请将 edgesForExtendedLayout 细化为 还将extendedLayoutIncludesOpaqueBars 属性设置为 。 (extendedLayoutIncludesOpaqueBars 的默认值为 NO。)

自动调整ScrollViewInsets

如果您不希望滚动视图的内容插入自动进行 调整后,将automaticallyAdjustsScrollViewInsets 设置为NO。 (这 automaticallyAdjustsScrollViewInsets 的默认值为 YES。)

topLayoutGuide、bottomLayoutGuide

topLayoutGuidebottomLayoutGuide 属性表示 视图控制器视图中顶部或底部条边的位置。 如果条应该与视图的顶部或底部重叠,您可以使用 Interface Builder 通过创建相对于栏来定位视图 约束到 topLayoutGuide 的底部或顶部 底部布局指南。 (如果没有条应该与视图重叠,则底部 topLayoutGuide 同视图顶部和顶部 bottomLayoutGuide 与视图底部相同。)两者 请求时延迟创建属性。

请参考apple doc

【讨论】:

iOS6下无法编译。我觉得应该写成performselector... 是的,这就是为什么我将选择器检查包含在 if 条件中,if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) 如果我没有导航栏,这将不起作用。在这种情况下,我的视图延伸到状态栏后面.. 我和@VanDuTran 有同样的问题。如果导航栏被隐藏,edgesForExtendedLayout 将无济于事。 它可以工作,但是......不再有半透明效果......我们怎样才能保持半透明效果......【参考方案2】:

您不必计算将所有内容向下移动多远,为此有一个内置属性。在 Interface Builder 中,突出显示您的视图控制器,然后导航到属性检查器。在这里,您会在“扩展边缘”一词旁边看到一些复选框。如您所见,在第一个屏幕截图中,默认选择是内容显示在顶部和底部栏下,而不是在不透明栏下,这就是为什么将栏样式设置为不透明对您有用的原因。

正如您在第一个屏幕截图中所看到的,导航栏下方隐藏着两个 UI 元素。 (我在 IB 中启用了线框来说明这一点)这些元素,一个 UIButton 和一个 UISegmentedControl 都将它们的“y”原点设置为零,并且视图控制器设置为允许顶部栏下方的内容。

第二个屏幕截图显示了当您取消选中“顶部栏下方”复选框时会发生什么。如您所见,视图控制器视图已适当向下移动,使其 y 原点位于导航栏的正下方。

这也可以通过使用-[UIViewController edgesForExtendedLayout] 以编程方式完成。这是edgeForExtendedLayout 和UIRectEdge 的类参考链接

[self setEdgesForExtendedLayout:UIRectEdgeNone];

【讨论】:

如何只在 .xib 中查看? 我在视图中添加了一个标签,并按照您的指示进行操作,但这对我不起作用 @bobics XIB 问题的答案是,“你不能。”反正不是通过IB。提交雷达并希望 Apple 最终解决它。 感谢@0x7fffffff,这正是我正在寻找的信息,非常有帮助。【参考方案3】:

我以编程方式创建了我的视图,这最终对我有用:

- (void) viewDidLayoutSubviews 
    // only works for iOS 7+
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) 
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;

        // snaps the view under the status bar (iOS 6 style)
        viewBounds.origin.y = topBarOffset * -1;

        // shrink the bounds of your view to compensate for the offset
        viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1);
        self.view.bounds = viewBounds;
    

Source(在第 39 页底部的 topLayoutGuide 部分)。

【讨论】:

终于找到了一个真正适用于此的答案。干得好! 为了解决隐藏导航栏时视图控制器的视图显示在状态栏下的问题,这是将视图捕捉到状态栏下的代码。 注意:这会将视图的底部推离屏幕。 另外,除非你是为only iOS7 构建的,否则上面的代码会抛出一个错误——topLayoutGuide is only iOS7. 另请注意,当您的主视图是 UITableView 时,每次滚动都会调用 viewDidLayoutSubviews。您的 UITableView 将按比例缩小,直到其高度为 15 像素。添加一个标志以仅运行此代码一次。 ;)【参考方案4】:

Swift 3 / Swift 4 解决方案也适用于 iOS 10+ 中的 NIB/XIB 文件:

override func viewDidLoad() 
    super.viewDidLoad()

    edgesForExtendedLayout = []

【讨论】:

这对我有帮助...如此简单。谢谢:-) 谢谢,真的很有帮助 这是 10.x Swift 3+ IMO 的最佳解决方案【参考方案5】:

如果您希望视图具有半透明导航栏(这很不错),您必须设置 contentInset 或类似的。

这是我的做法:

// Check if we are running on ios7
if([[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."][0] intValue] >= 7) 
      CGRect statusBarViewRect = [[UIApplication sharedApplication] statusBarFrame];
      float heightPadding = statusBarViewRect.size.height+self.navigationController.navigationBar.frame.size.height;

      myContentView.contentInset = UIEdgeInsetsMake(heightPadding, 0.0, 0.0, 0.0);

【讨论】:

为什么不能和7.0直接比较 大声笑我明白了:检查添加了次要版本的特定版本不太健壮。但是您正在检查该值是否更大或等于,因此与 7.0 相比在这里就可以了;) @leena - 这是 7.x 及更高版本中的功能 - 所以我检查版本是否为 7 或更高版本并跳过检查中的次要修订。 Tabbar 后面显示的 tableView 出现问题。这使得我的表格的最后一行永远不会在 Tabbar 上方滚动。我这样修复它: myTableView.contentInset = UIEdgeInsetsMake(0, 0.0, TabbarHeight, 0) contentInsetUIScrollView 的属性。如果我的主视图不是UIScrollView 的子类怎么办。那我该如何解决重叠问题呢?【参考方案6】:

edgesForExtendedLayout 适用于 iOS 7。但是,如果您跨 iOS 7 SDK 构建应用程序并将其部署到 iOS 6 中,导航栏将显示为半透明,并且视图位于其下方。因此,要为 iOS 7 和 iOS 6 修复它,请执行以下操作:

self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;   // iOS 7 specific

【讨论】:

【参考方案7】:

在您的应用程序 plist 文件中添加一行,将其命名为“基于控制器的状态栏外观”并将其设置为 NO

【讨论】:

【参考方案8】:

最简单的技巧是打开NIB文件并执行以下两个简单步骤:

    只需切换它并将其设置为您喜欢的:

    选择那些你想下移的 UIView's/UIIMageView's/...。就我而言,只有徽标重叠,我将增量设置为 +15; (如果您在第 1 步中选择了 iOS 7,则为 -15)

以及结果

【讨论】:

它有效,但这看起来是一个难以维护的解决方案。最好只是解决问题而不是修补它。 最好以编程方式对所有视图的子视图执行此操作,因为如果应用于主视图则不起作用【参考方案9】:

快速解决方案:

override func viewWillAppear(animated: Bool) 
    super.viewWillAppear(animated)
    self.edgesForExtendedLayout = UIRectEdge.None

【讨论】:

现在是 edgesForExtendedLayout = [] 因为这是一个公开的答案,我们不应该忘记致电:super.viewWillAppear(animated)【参考方案10】:

我想扩展 Stunner 的答案,并添加一个 if 语句来检查它是否是 iOS-7,因为当我在 iOS 6 上测试它时,我的应用程序会崩溃。

添加将是:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

所以我建议将此方法添加到您的 MyViewControler.m 文件中:

- (void) viewDidLayoutSubviews 
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) 
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;
        viewBounds.origin.y = topBarOffset * -1;
        self.view.bounds = viewBounds;
    

【讨论】:

【参考方案11】:

斯威夫特 3

override func viewWillAppear(_ animated: Bool) 
    self.edgesForExtendedLayout = []

【讨论】:

【参考方案12】:

我有一个场景,我使用 Apple 编写的 BannerViewController 来显示我的广告和嵌入在 BannerViewController 中的 ScrollViewController。

为了防止导航栏隐藏我的内容,我必须进行两项更改。

1) 修改 BannerViewController.m

- (void)viewDidLoad

   [super viewDidLoad];
   float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
   if (systemVersion >= 7.0) 
      self.edgesForExtendedLayout = UIRectEdgeNone;
   

2) 修改我的 ScrollViewContoller

- (void)viewDidLoad

    [super viewDidLoad];
    float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (systemVersion >= 7.0) 
        self.edgesForExtendedLayout = UIRectEdgeBottom;
    

现在广告可以正确显示在视图的底部,而不是被导航栏覆盖,并且顶部的内容不会被截断。

【讨论】:

【参考方案13】:

只要在视图中设置如下代码就会出现。

  if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) 
self.edgesForExtendedLayout = UIRectEdgeNone;
 

【讨论】:

这是在我的情况下唯一有效的方法。【参考方案14】:

像这样对顶部布局进行约束

【讨论】:

【参考方案15】:

Swift 4.2 - Xcode 10.0 - iOS 12.0:

if #available(iOS 11.0, *)  else 
  self.edgesForExtendedLayout = []
  self.navigationController?.view.backgroundColor = .white

【讨论】:

【参考方案16】:

对我来说,最简单的解决方案是在 plist 中添加两个键

【讨论】:

+1,我有“状态栏最初隐藏”=YES,但是当添加“查看基于控制器的状态栏外观”=NO 时,我摆脱了状态栏。【参考方案17】:

将下拉列表中的“基于视图控制器的状态栏外观”键添加为info.plist 中的一行。像这样:

【讨论】:

很有趣。它对我的 cocos2d 项目有所帮助。当我切换此选项时,我可以看到顶部状态栏完全消失或出现。【参考方案18】:

我的 iPad 应用程序(armv7、armv7s、amr64)也遇到了同样的问题,只是通过呈现另一个 UIViewController 并在解除它们后进入状态栏下的导航栏... 我花了很多时间来寻找任何解决方案。我正在使用故事板和 UIViewController 的 InterfaceBuilder,这使得我从 FullScreen -> Current Context 设置 Presentation 并解决了这个问题。它仅适用于我的应用程序,适用于 iPads => iOS8.0(使用 iOS8.1 进行测试),并且适用于 iOS 7.1 的 iPad 不起作用!!

【讨论】:

就我而言,我的主视图与我的 tabBar 重叠,我不知道为什么。事实证明,Extend Edges > Under Bottom Bars 已被选中。真的很难注意到它,因为我的应用程序的背景是白色的,它只会在我的 tabBar 上产生一定程度的不透明度。谢谢!【参考方案19】:

在 iOS 7 中隐藏状态栏的步骤:

1.转到您的应用程序 info.plist 文件。

2.And Set,查看基于控制器的状态栏外观:Boolean NO

希望我解决了状态栏问题.....

【讨论】:

【参考方案20】:

在我的情况下 loadView() 被中断 这段代码: self.edgesForExtendedLayout = UIRectEdgeNone

但删除 loadView() 后一切正常

【讨论】:

以上是关于在 iOS 7 中,状态栏和导航栏出现在我的视图边界上的主要内容,如果未能解决你的问题,请参考以下文章

iOS 7 UI 变化:状态栏和导航控制器

iOS 11、状态栏、导航栏和 UIScrollview

如何添加覆盖所有其他视图(包括导航栏和状态栏)的暗屏?

导航栏和视图之间的分隔符 - iOS 7

Xcode 13 - swift OS 15 中的导航栏和状态栏文本颜色变化

iOS 7 中 UIActivityViewControllers 的模态状态栏和导航栏文本颜色