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

我最近下载了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 stackoverflow.com/a/18976660/235206 的答案作为解决方案

标签: ios ios7


【解决方案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] 以编程方式完成。这是edgeForExtendedLayoutUIRectEdge 的类参考链接

[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 将按比例缩小,直到其高度为 15px。添加一个标志以仅运行此代码一次。 ;)
【解决方案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文件并执行以下两个简单步骤:

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

      1. 选择那些你想下移的 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() 后一切正常

                  【讨论】:

                    猜你喜欢
                    • 2013-08-24
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多