152

在探索Xcode9 Beta时,在界面构建器视图层次结构查看器上发现了安全区域。很好奇并试图了解 Apple 文档上的安全区域,主要是文档说“与自动布局直接交互的视图区域”但它并不满足我,我想知道这个新事物的实际用途。

有人有线索吗?

在此处输入图像描述

Apple 文档中关于安全区域的结论段落。

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

4

5 回答 5

290

Safe Area 是一个布局指南(Safe Area Layout Guide
布局指南,代表视图中未被条形和其他内容遮挡的部分。在 iOS 11+ 中,Apple 弃用了顶部和底部布局指南,并用单一安全区域布局指南取而代之。

当视图在屏幕上可见时,本指南会反映视图中未被其他内容覆盖的部分。视图的安全区域反映了导航栏、选项卡栏、工具栏和其他遮挡视图控制器视图的祖先所覆盖的区域。(在 tvOS 中,安全区域包含屏幕的边框,由overscanCompensationInsetsUIScreen 的属性定义。)它还覆盖了视图控制器additionalSafeAreaInsets属性定义的任何额外空间。如果视图当前未安装在视图层次结构中,或者在屏幕上尚不可见,则布局指南始终与视图的边缘匹配。

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

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

在此处输入图像描述


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

安全区域布局: 在此处输入图像描述

自动布局

在此处输入图像描述


如何使用安全区域布局?

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

  • 如果未启用,则启用“安全区域布局”。
  • 如果它们显示与超级视图的连接,则删除“所有约束”并使用安全布局锚重新附加所有约束。或 双击约束并编辑从超级视图到 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 Official Documentation for Safe Area Layout Guide


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

于 2017-07-26T18:04:40.437 回答
20

正如最新的人机界面指南所建议的那样,当我试图调整基于 SpriteKit 的应用程序以避免新 iPhone X 的圆边和“缺口”时,我想提一些首先引起我注意的事情:The new property safeAreaLayoutGuideof UIViewneeds to在视图被添加到层次结构(例如, on )后被查询-viewDidAppear:,以便报告有意义的布局框架(否则,它只返回全屏大小)。

从物业的文件中:

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

(强调我的)

如果您早点阅读它-viewDidLoad:layoutFrame指南的将{{0, 0}, {375, 812}}不是预期的{{0, 44}, {375, 734}}

于 2017-09-15T05:58:24.457 回答
18

在此处输入图像描述

  • 在 iOS 7.0–11.0 早期的 < Deprecated >UIKit使用topLayoutGuide & bottomLayoutGuide这是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
        }

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

于 2017-10-10T11:28:08.837 回答
8

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

有关更多信息,请参阅链接

于 2017-08-17T04:58:29.000 回答
5

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

安全区域是系统 UI 元素之间的区域,这些元素是状态栏、导航栏和工具栏或选项卡栏。因此,当您向应用添加状态栏时,安全区域会缩小。当您向应用添加导航栏时,安全区域会再次缩小。

在 iPhone X 上,即使没有显示条形图,安全区域也会在纵向屏幕的顶部和底部边缘提供额外的插图。在横向中,安全区域从屏幕和主页指示器的侧面插入。

这取自 Apple 的视频Designing for iPhone X,他们还可视化了不同元素如何影响安全区域。

于 2017-09-13T09:48:46.400 回答