获得安全区域嵌入顶部和底部高度

Tul*_*leb 129 ios safearealayoutguide iphone-x

在新的iPhone X上,为不安全区域获得顶部和底部高度最合适的方法是什么?

在此输入图像描述

use*_*419 301

试试这个 :

目标C中

if (@available(iOS 11.0, *)) {
    UIWindow *window = UIApplication.sharedApplication.keyWindow;
    CGFloat topPadding = window.safeAreaInsets.top;
    CGFloat bottomPadding = window.safeAreaInsets.bottom;
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特

if #available(iOS 11.0, *) {
    let window = UIApplication.shared.keyWindow
    let topPadding = window?.safeAreaInsets.top
    let bottomPadding = window?.safeAreaInsets.bottom
}
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说似乎不起作用 - 打印出UIApplication.shared.keyWindow的值?.safeAreaInsets返回全0.有任何想法吗? (9认同)
  • 对我而言,`keyWindow`始终为'nil',所以我将其更改为`windows [0]`,并从可选链接中删除了'?`,然后它起作用了。 (3认同)
  • 我做了,我可以约束任何视图的safeAreaLayoutGuides,但直接打印出关键窗口的值safeAreaInsets只返回一个零rect.这是有问题的,因为我需要手动约束已添加到关键窗口但不在根视图控制器的视图层次结构中的视图. (2认同)
  • 使用iPhone X时对我不起作用 (2认同)
  • 只有当控制器的视图已经出现时它才起作用。 (2认同)

Lad*_*lav 62

要获得布局指南之间的高度,您就可以了

let guide = view.safeAreaLayoutGuide
let height = guide.layoutFrame.size.height
Run Code Online (Sandbox Code Playgroud)

所以full frame height = 812.0,safe area height = 734.0

下面是绿色视图具有框架的示例 guide.layoutFrame

在此输入图像描述

  • 一旦布置了视图,这将为您提供正确的答案 (3认同)
  • 实际上@ user6788419的答案看起来也很好而且更短. (2认同)

bso*_*sod 57

斯威夫特4

使用约束将视图固定到安全区域锚点可以在视图控制器的生命周期中的任何点完成,因为约束由幕后的自动布局API处理.但是,要访问这些安全区域的值以确定其高度,需要等到视图控制器生命周期的后期,理想情况下viewDidLayoutSubviews().

这会插入任何视图控制器:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    var topSafeArea: CGFloat
    var bottomSafeArea: CGFloat

    if #available(iOS 11.0, *) {
        topSafeArea = view.safeAreaInsets.top
        bottomSafeArea = view.safeAreaInsets.bottom
    } else {
        topSafeArea = topLayoutGuide.length
        bottomSafeArea = bottomLayoutGuide.length
    }

    // safe area values are now available to use

}
Run Code Online (Sandbox Code Playgroud)

我更喜欢这种方法让它脱离窗口,因为这是Apple设计API的方式.当视图控制器中已存在所有内容时,请勿引用窗口等无关对象.通过使用viewDidLayoutSubviews(),安全区域值在方向更改期间更新,双高度状态栏以及视图及其安全区域的所有其他突变.

  • 请使用let topSafeArea:CGFloat声明! (3认同)

moj*_*awi 21

这里的所有答案都很有帮助,感谢所有提供帮助的人。

但是,正如我所见,安全区域主题有点混乱,似乎没有很好的文档记录。

因此,我将在此处尽可能地对其进行总结以使其易于理解safeAreaInsetssafeAreaLayoutGuide并且LayoutGuide

在 iOS 7 中,Apple 在 中引入了topLayoutGuidebottomLayoutGuide属性UIViewController,它们允许您创建约束以防止您的内容被 UIKit 栏(如状态、导航或标签栏)隐藏 这些布局指南可以指定对内容的约束,避免它被顶部或底部导航元素(UIKit 栏、状态栏、导航栏或标签栏……)隐藏。

因此,例如,如果您想让 tableView 从顶部屏幕开始,您已经完成了以下操作:

self.tableView.contentInset = UIEdgeInsets(top: -self.topLayoutGuide.length, left: 0, bottom: 0, right: 0)
Run Code Online (Sandbox Code Playgroud)

在 iOS 11 中,Apple 已弃用这些属性,将它们替换为单个安全区域布局指南

根据 Apple 的安全区域

安全区域可帮助您将视图放置在整个界面的可见部分。UIKit 定义的视图控制器可以将特殊视图放置在您的内容之上。例如,导航控制器在底层视图控制器内容的顶部显示导航栏。即使这样的视图是部分透明的,它们仍然会遮挡它们下面的内容。在 tvOS 中,安全区域还包括屏幕的过扫描插图,代表屏幕边框覆盖的区域。

下面是 iPhone 8 和 iPhone X 系列中突出显示的安全区域:

在此处输入图片说明

safeAreaLayoutGuide是一个属性UIView

要获得 的高度safeAreaLayoutGuide

extension UIView {
   var safeAreaHeight: CGFloat {
       if #available(iOS 11, *) {
        return safeAreaLayoutGuide.layoutFrame.size.height
       }
       return bounds.height
  }
}
Run Code Online (Sandbox Code Playgroud)

这将返回图片中箭头的高度。

现在,如何获得顶部的“缺口”和底部的主屏幕指示器高度?

这里我们将使用 safeAreaInsets

视图的安全区域反映了导航栏、标签栏、工具栏和其他遮蔽视图控制器视图的祖先未覆盖的区域。(在 tvOS 中,安全区域反映了屏幕边框未覆盖的区域。)通过将此属性中的插图应用于视图的边界矩形,您可以获得视图的安全区域。如果视图当前未安装在视图层次结构中,或者尚未在屏幕上可见,则此属性中的边缘插入为 0。

下面将显示 iPhone 8 和 iPhone X 系列之一上的不安全区域以及与边缘的距离。

在此处输入图片说明

在此处输入图片说明

现在,如果添加了导航栏

在此处输入图片说明

在此处输入图片说明

那么,现在如何获得不安全区域的高度呢?我们将使用safeAreaInset

这是解决方案,但它们在一个重要的事情上有所不同,

第一:

self.view.safeAreaInsets
Run Code Online (Sandbox Code Playgroud)

这将返回 EdgeInsets,您现在可以访问顶部和底部以了解插入,

第二个:

UIApplication.shared.windows.first{$0.isKeyWindow }?.safeAreaInsets
Run Code Online (Sandbox Code Playgroud)

第一个您正在查看视图插入,因此如果有导航栏,它将被考虑,但是第二个您正在访问窗口的 safeAreaInsets,因此不会考虑导航栏


Sco*_*des 9

None of the other answers here worked for me, but this did.

var topSafeAreaHeight: CGFloat = 0
var bottomSafeAreaHeight: CGFloat = 0

  if #available(iOS 11.0, *) {
    let window = UIApplication.shared.windows[0]
    let safeFrame = window.safeAreaLayoutGuide.layoutFrame
    topSafeAreaHeight = safeFrame.minY
    bottomSafeAreaHeight = window.frame.maxY - safeFrame.maxY
  }
Run Code Online (Sandbox Code Playgroud)

  • 您的代码将在视图控制器生命周期的任何部分工作。如果您想使用 view.safeAreaInsets.top,那么您需要确保在 viewDidAppear 或更高版本之后调用它。在 viewDidLoad 中,您将无法获得具有正确值的 view.safeAreaInsets.top,因为它尚未初始化。 (2认同)
  • 迄今为止最好的答案 (2认同)

use*_*695 7

斯威夫特 5,Xcode 11.4

`UIApplication.shared.keyWindow` 
Run Code Online (Sandbox Code Playgroud)

它将给出弃用警告。''keyWindow' 在 iOS 13.0 中已弃用:不应用于支持多个场景的应用程序,因为它会在所有连接的场景中返回一个关键窗口,因为连接的场景。我用这种方式。

extension UIView {

    var safeAreaBottom: CGFloat {
         if #available(iOS 11, *) {
            if let window = UIApplication.shared.keyWindowInConnectedScenes {
                return window.safeAreaInsets.bottom
            }
         }
         return 0
    }

    var safeAreaTop: CGFloat {
         if #available(iOS 11, *) {
            if let window = UIApplication.shared.keyWindowInConnectedScenes {
                return window.safeAreaInsets.top
            }
         }
         return 0
    }
}

extension UIApplication {
    var keyWindowInConnectedScenes: UIWindow? {
        return windows.first(where: { $0.isKeyWindow })
    }
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*ael 7

这适用于整个视图生命周期,作为 Swift 中简单的两行解决方案:

let top    = UIApplication.shared.windows[0].safeAreaInsets.top
let bottom = UIApplication.shared.windows[0].safeAreaInsets.bottom
Run Code Online (Sandbox Code Playgroud)

我个人需要它,viewDidLoadview.safeAreaInsets尚未计算。


小智 6

在 iOS 11 中,有一种方法可以告知 safeArea 何时发生变化。

override func viewSafeAreaInsetsDidChange() {
    super.viewSafeAreaInsetsDidChange()
    let top = view.safeAreaInsets.top
    let bottom = view.safeAreaInsets.bottom
}
Run Code Online (Sandbox Code Playgroud)