首页 文章

状态栏和导航栏显示在iOS 7中的视图边界上

提问于
浏览
424

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

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

{{0,0},{320,568}}

这导致我的内容出现在导航栏和状态栏下方 .

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

我该如何解决这个问题?

Update:

我找到了解决这个特定问题的方法 . 将导航栏的半透明属性设置为NO:

self.navigationController.navigationBar.translucent = NO;

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

但是,当您希望导航栏为半透明时,我还没有找到针对该案例的修复程序 . 例如,全屏查看照片,我希望导航栏是半透明的,并且要在其下面构建视图 . 这是有效的,但当我切换显示/隐藏导航栏时,我经历了甚至更奇怪的结果 . 第一个子视图(UIScrollView)每次都会更改其边界 .

20 回答

  • 110

    我以编程方式创建了我的视图,最终为我工作:

    - (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 部分) .

  • 3

    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
    
  • 0

    Swift 3

    override func viewWillAppear(_ animated: Bool) {
        self.edgesForExtendedLayout = []
    }
    
  • 9

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

    • 只需切换并将其设置为您喜欢的那个:

    Enter image description here

    • 选择要移动的UIView 's/UIIMageView' s / ...在我的情况下,只有徽标重叠,我将delta设置为15; (如果您在步骤1中选择了iOS 7,则为-15)

    Enter image description here

    the result

    Before

    After

  • 1

    只需在视图中设置以下代码即可出现 .

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

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

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

    2.And Set,View基于控制器的状态栏外观:布尔值NO

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

  • 22

    我想扩展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;
        }
    }
    
  • 7

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

    enter image description here

  • 493

    我有一个场景,我使用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;
        }
    }
    

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

  • 2

    iPad(armv7,armv7s,amr64)我的应用程序遇到了同样的问题,只是通过呈现另一个UIViewController并在解除它们后,状态栏下的导航栏...我花了很多时间找到任何解决方案 . 我正在使用storyboard和在InterfaceBuilder中使用UIViewController,这让我很糟糕,我从FullScreen设置了Presentation - > Current Context并解决了这个问题 . 它适用于我的应用程序仅适用于iPad => iOS8.0(使用iOS8.1测试)和适用于iOS 7.1的iPad无法正常工作!!
    see screenshot

  • 5

    Swift 4.2 - Xcode 10.0 - iOS 12.0:

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

    在您的应用程序plist文件中添加一行,将其命名为"View controller-based status bar appearance"并将其设置为NO .

  • 10

    在我的情况下,loadView()中断
    此代码:self.edgesForExtendedLayout = UIRectEdgeNone

    但删除loadView()后一切正常

  • 0

    像这样对Top Layout进行约束
    enter image description here

  • 0

    将下拉列表中的键"View Controller-based status bar appearance"添加为 info.plist 中的一行 . 像这样的东西:

    Enter image description here

  • 2

    Swift解决方案:

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.edgesForExtendedLayout = UIRectEdge.None
    }
    
  • 9

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

    override func viewDidLoad() {
        super.viewDidLoad()
    
        edgesForExtendedLayout = []
    }
    
  • 4

    您可以通过在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中不推荐使用该属性 . 如果您当前指定的wantFullScreenLayout = NO,则视图控制器在iOS 7中运行时可能会在意外的屏幕位置显示其内容 . 要调整视图控制器的视图布局,UIViewController提供以下属性:edgesForExtendedLayout edgesForExtendedLayout属性使用UIRectEdge类型,该类型除了指定none和all之外,还指定每个矩形的四条边 . 使用edgesForExtendedLayout指定视图的哪些边应该扩展,而不管条形半透明度 . 默认情况下,此属性的值为UIRectEdgeAll . extendedLayoutIncludesOpaqueBars如果您的设计使用不透明条形,则还可以通过将extendedLayoutIncludesOpaqueBars属性设置为NO来细化edgesForExtendedLayout . (extendedLayoutIncludesOpaqueBars的默认值为NO . )automaticAdjustsScrollViewInsets如果您不希望自动调整滚动视图的内容插入,请将AutomaticAdjustsScrollViewInsets设置为NO . (automaticAdjustsScrollViewInsets的默认值为YES . )topLayoutGuide,bottomLayoutGuide topLayoutGuide和bottomLayoutGuide属性指示视图控制器视图中顶部或底部条边的位置 . 如果条形图应与视图的顶部或底部重叠,则可以使用Interface Builder通过在topLayoutGuide底部或bottomLayoutGuide顶部创建约束来相对于条形定位视图 . (如果没有条形图与视图重叠,则topLayoutGuide的底部与视图的顶部相同,bottomLayoutGuide的顶部与视图的底部相同 . )两个属性在请求时都会延迟创建 .

    请参考,apple doc

  • 1

    你不必计算将所有东西都降下来的距离,这里有一个属性 . 在Interface Builder中,突出显示视图控制器,然后导航到属性检查器 . 在这里,您会看到“Extend Edges”字样旁边的一些复选框 . 正如您所看到的,在第一个屏幕截图中,默认选择是内容显示在顶部和底部条形下,而不是在不透明条形下,这就是为什么将条形样式设置为不半透明的原因 .

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

    enter image description here

    第二个屏幕截图显示取消选中“Under Top Bars”复选框时会发生什么 . 如您所见,视图控制器视图已正确向下移动,其y原点位于导航栏下方 .

    enter image description here

    这也可以通过 -[UIViewController edgesForExtendedLayout] 的使用以编程方式完成 . 这是edgeForExtendedLayout的类引用的链接,以及UIRectEdge的链接

    [self setEdgesForExtendedLayout:UIRectEdgeNone];
    
  • 1

    如果您希望视图具有半透明导航栏(这很好),您必须设置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);
    }
    

相关问题