Xcode 9的安全区域


150

在探索Xcode9 Beta时,在“界面”构建器的“视图层次结构查看器”中找到了“ 安全区域 ”。好奇并试图了解Apple文档上的“安全区域”,要点是文档说:“与Auto布局直接交互的视图区域”,但是它令我不满意,我想知道这个新事物的实际使用。

有人有线索吗?

在此处输入图片说明

Apple文档“安全区域”的结论段落。

UILayoutGuide类旨在执行以前由虚拟视图执行的所有任务,但以更安全,更有效的方式执行。布局指南未定义新视图。他们不参与视图层次结构。相反,他们只是在自己的视图的坐标系中定义了一个矩形区域,该区域可以与“自动布局”交互。


1
您可以观看WWDC会话。一切都在那里解释。我不确定这个名字。Xcode或InterfaceBuilder的名称。
Maik639

Answers:


282

安全区域是一种布局指南(安全区域布局指南
布局指南,表示视图中没有被条形图和其他内容遮盖的部分。在iOS 11+中,Apple不赞成使用顶部和底部布局指南,而是将其替换为一个安全区域布局指南。

当视图在屏幕上可见时,本指南将反映该视图未被其他内容覆盖的部分。视图的安全区域反映了导航栏,标签栏,工具栏和其他祖先覆盖的区域,这些区域使视图控制器的视图变得模糊。(在tvOS中,安全区域合并了overscanCompensationInsetsUIScreen属性定义的屏幕边框。)它还覆盖了视图控制器additionalSafeAreaInsets属性定义的任何其他空间。如果视图当前未安装在视图层次结构中,或者尚未在屏幕上显示,则布局指南始终与视图的边缘匹配。

对于视图控制器的根视图,此属性中的安全区域表示被遮盖的视图控制器内容的整个部分,以及您指定的任何其他插图。对于视图层次结构中的其他视图,安全区域仅反映该视图中被遮盖的部分。例如,如果视图完全在其视图控制器的根视图的安全区域内,则此属性中的边插入为0。

根据Apple的说法,Xcode 9-发行说明
Interface Builder使用UIView.safeAreaLayoutGuide代替了UIViewController中已弃用的顶部和底部布局指南。要使用新的安全区域,请在文件检查器中为视图控制器选择“安全区域布局指南”,然后在内容和新的安全区域锚点之间添加约束。这样可以防止您的内容被顶部和底部的条以及tvOS上的过扫描区域所遮盖。部署到早期版本的iOS时,对安全区域的约束将转换为“顶部”和“底部”。

在此处输入图片说明


这是现有(顶部和底部)布局指南和“安全区域布局指南”之间的比较(以产生相似的视觉效果),仅供参考。

安全区域布局: 在此处输入图片说明

自动版式

在此处输入图片说明


如何使用安全区域布局?

请按照以下步骤查找解决方案:

  • 如果未启用,请启用“安全区域布局”。
  • 如果它们显示与Super View的连接,则删除“所有约束”,然后使用安全的布局锚点重新附加所有约束。或双击约束,然后编辑从超级视图到SafeArea锚点的连接

这是示例快照,如何启用安全区域布局和编辑约束。

在此处输入图片说明

这是上述更改的结果

在此处输入图片说明


使用SafeArea进行布局
设计为iPhone X设计时,必须确保布局充满屏幕,并且不会被设备的圆角,传感器外壳或用于访问主屏幕的指示器所遮盖。

在此处输入图片说明

大多数使用标准的,系统提供的UI元素(例如导航栏,表格和集合)的应用都会自动适应设备的新外形。背景材料延伸到显示器的边缘,并且UI元素已适当插入和放置。

在此处输入图片说明

对于具有自定义布局的应用程序,支持iPhone X也应该相对容易一些,尤其是如果您的应用程序使用自动布局并遵守安全区域和边距布局指南。

在此处输入图片说明


这是示例代码(
请参阅安全区域布局指南: 如果在代码中创建约束,请使用UIView的safeAreaLayoutGuide属性获取相关的布局锚点。让我们在代码中重新创建上面的Interface Builder示例,以查看其外观:

假设我们在视图控制器中将绿色视图作为属性:

private let greenView = UIView()

我们可能有一个函数来设置从viewDidLoad调用的视图和约束:

private func setupView() {
  greenView.translatesAutoresizingMaskIntoConstraints = false
  greenView.backgroundColor = .green
  view.addSubview(greenView)
}

像往常一样使用根视图的layoutMarginsGuide创建前缘和尾缘边距约束:

 let margins = view.layoutMarginsGuide
    NSLayoutConstraint.activate([
      greenView.leadingAnchor.constraint(equalTo: margins.leadingAnchor),
      greenView.trailingAnchor.constraint(equalTo: margins.trailingAnchor)
 ])

现在,除非您仅以iOS 11为目标,否则您将需要使用#available来包装安全区域布局指南约束,并退回到iOS早期版本的顶部和底部布局指南:

if #available(iOS 11, *) {
  let guide = view.safeAreaLayoutGuide
  NSLayoutConstraint.activate([
   greenView.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0),
   guide.bottomAnchor.constraintEqualToSystemSpacingBelow(greenView.bottomAnchor, multiplier: 1.0)
   ])

} else {
   let standardSpacing: CGFloat = 8.0
   NSLayoutConstraint.activate([
   greenView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: standardSpacing),
   bottomLayoutGuide.topAnchor.constraint(equalTo: greenView.bottomAnchor, constant: standardSpacing)
   ])
}


结果:

在此处输入图片说明


UIView扩展之后,可以轻松地以编程方式使用SafeAreaLayout。

extension UIView {

  // Top Anchor
  var safeAreaTopAnchor: NSLayoutYAxisAnchor {
    if #available(iOS 11.0, *) {
      return self.safeAreaLayoutGuide.topAnchor
    } else {
      return self.topAnchor
    }
  }

  // Bottom Anchor
  var safeAreaBottomAnchor: NSLayoutYAxisAnchor {
    if #available(iOS 11.0, *) {
      return self.safeAreaLayoutGuide.bottomAnchor
    } else {
      return self.bottomAnchor
    }
  }

  // Left Anchor
  var safeAreaLeftAnchor: NSLayoutXAxisAnchor {
    if #available(iOS 11.0, *) {
      return self.safeAreaLayoutGuide.leftAnchor
    } else {
      return self.leftAnchor
    }
  }

  // Right Anchor
  var safeAreaRightAnchor: NSLayoutXAxisAnchor {
    if #available(iOS 11.0, *) {
      return self.safeAreaLayoutGuide.rightAnchor
    } else {
      return self.rightAnchor
    }
  }

}

这是Objective-C中的示例代码:


这是Apple Developer 安全区域布局指南的官方文档


需要安全区域来处理iPhone-X的用户界面设计。这是有关如何使用“安全区域布局”为iPhone-X设计用户界面的基本指南


至于margins和之间的区别view.leadingAnchor:在使用let margins = view.layoutMarginsGuide和以后使用时margins.leadingAnchor,您将视图限制在视图的边缘。这将在侧面增加一些额外的空间。如果您不想要它,则只需使用它view.leadingAnchorview.trailingAnchor并且您就不会在左侧或右侧看到任何空白...
亲爱的

“视图的安全区域反映了导航栏,选项卡栏,工具栏和其他祖先覆盖的区域,这些区域使视图控制器的视图变得模糊”,您不是没有覆盖吗?该文件说“ 不受酒吧和其他内容的影响”。
亲爱的

我在Xcode 10.1中看到了一个奇怪的行为,其中“安全区域”不会扩展到全屏视图的屏幕底部。我相信是由于不小心将“标签栏”拖到底部,然后将其删除而造成的。我在.storyboard文件中找到了这一行,该文件是使用文本编辑器手动删除的。<simulatedToolbarMetrics key =“ simulatedBottomBarMetrics” />。这样就解决了。
戴夫·哈伯德

20

我想提的东西,首先吸引我,当我试图去适应一个基于SpriteKit应用程序内,以避免圆边和新的iPhone X的“缺口”,通过最新的建议人机界面指南:新属性safeAreaLayoutGuideUIView需求,将视图添加到层​​次结构后(例如on -viewDidAppear:),将被查询, 以报告有意义的布局框架(否则,它仅返回全屏尺寸)。

从物业的文件:

布局指南,表示视图中没有被条形图和其他内容遮盖的部分。 当视图在屏幕上可见时,本指南将反映该视图未被导航栏,标签栏,工具栏和其他祖先视图覆盖的部分。(在tvOS中,安全区域反映的是未被屏幕边框覆盖的区域。)如果视图当前未安装在视图层次结构中,或者在屏幕上尚不可见,则布局参考线的边缘将等于视图的边缘

(强调我的)

如果您早读过该指南-viewDidLoad:,则layoutFrame该指南将{{0, 0}, {375, 812}}代替预期的{{0, 44}, {375, 734}}


同样在这里。我总是跳过一个类型的可用属性,仅以它们的名称为指导,而没有完全阅读文档……
Nicolas Miari

18

在此处输入图片说明

  • iOS 7.0–11.0中的早期版本< 已弃用 > UIKit使用topLayoutGuidebottomLayoutGuide这是UIView属性
  • iOS11 +使用safeAreaLayoutGuide也是UIView属性

  • 从文件检查器中启用“ 安全区域布局指南”复选框。

  • 安全区域可帮助您将视图放置在整个界面的可见部分内。

  • tvOS中,安全区域还包括屏幕的过扫描插图,这些插图代表屏幕边框所覆盖的区域。

  • safeAreaLayoutGuide反映了视图的未被导航栏,选项卡栏,工具栏和其他祖先视图覆盖的部分。
  • 使用安全区域来辅助布置您的内容,例如UIButton

  • 在为iPhone X设计时,必须确保布局充满屏幕,并且不会被设备的圆角,传感器外壳或用于访问主屏幕的指示器所遮盖。

  • 确保背景延伸到显示器的边缘,并且垂直可滚动的布局(例如表格和集合)一直延续到底部。

  • iPhone X的状态栏比其他iPhone高。如果您的应用采用固定的状态栏高度来将内容定位在状态栏下方,则必须更新您的应用以根据用户的设备动态定位内容。请注意,当诸如录音和位置跟踪之类的后台任务处于活动状态时,iPhone X上的状态栏不会更改高度 print(UIApplication.shared.statusBarFrame.height)//44 for iPhone X, 20 for other iPhones

  • 归位指示器容器的高度为34分。

  • 启用“ 安全区域布局指南”后,您将看到在界面构建器中列出的安全区域约束属性。

在此处输入图片说明

您可以分别使用self.view.safeAreaLayoutGuide-

对象:

  self.demoView.translatesAutoresizingMaskIntoConstraints = NO;
    UILayoutGuide * guide = self.view.safeAreaLayoutGuide;
    [self.demoView.leadingAnchor constraintEqualToAnchor:guide.leadingAnchor].active = YES;
    [self.demoView.trailingAnchor constraintEqualToAnchor:guide.trailingAnchor].active = YES;
    [self.demoView.topAnchor constraintEqualToAnchor:guide.topAnchor].active = YES;
    [self.demoView.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor].active = YES;

迅速:

   demoView.translatesAutoresizingMaskIntoConstraints = false
        if #available(iOS 11.0, *) {
            let guide = self.view.safeAreaLayoutGuide
            demoView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
            demoView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
            demoView.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
            demoView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
        } else {
            NSLayoutConstraint(item: demoView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true
            NSLayoutConstraint(item: demoView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true
            NSLayoutConstraint(item: demoView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true
            NSLayoutConstraint(item: demoView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: 0).isActive = true
        }

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明


我发现此要点指南非常有用,但是“安全区域不包括导航栏,标签栏,工具栏和其他祖先视图”到底是什么意思?
Chewie The Chorkie

1
示例-如上一个屏幕屏幕上的工具栏(今天,日历和收件箱)一样,safreAreaGuide未涵盖该工具栏
杰克

8

Apple早在iOS 7中就将topLayoutGuide和bottomLayoutGuide作为UIViewController的属性引入。它们允许您创建约束,以防止内容被UIKit栏(例如状态,导航或标签栏)隐藏。这些布局指南在iOS 11中已弃用,并由一个安全区域布局指南代替。

请参阅链接以获取更多信息。


5

“安全区域布局指南”有助于避免在放置内容和控件时重叠系统UI元素。

安全区域是系统UI元素(状态栏,导航栏和工具栏或标签栏)之间的区域。因此,当您向应用程序添加状态栏时,安全区域会缩小。将导航栏添加到应用程序后,安全区域会再次缩小。

在iPhone X上,即使未显示任何条形图,“安全区域”也会从纵向屏幕的顶部和底部边缘提供额外的插图。在风景中,安全区域从屏幕和归位指示器的侧面插入。

这摘自Apple的视频《 iPhone X设计》,在其中他们还可视化了不同元素如何影响安全区域。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.