ios 获取安全区域插入顶部和底部高度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46829840/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get safe area inset top and bottom heights
提问by Tulleb
回答by user6788419
Try this :
尝试这个 :
In Objective C
在目标 C
if (@available(iOS 11.0, *)) {
UIWindow *window = UIApplication.sharedApplication.keyWindow;
CGFloat topPadding = window.safeAreaInsets.top;
CGFloat bottomPadding = window.safeAreaInsets.bottom;
}
In Swift
在斯威夫特
if #available(iOS 11.0, *) {
let window = UIApplication.shared.keyWindow
let topPadding = window?.safeAreaInsets.top
let bottomPadding = window?.safeAreaInsets.bottom
}
回答by Ladislav
To get the height between the layout guides you just do
要获得布局指南之间的高度,您只需执行
let guide = view.safeAreaLayoutGuide
let height = guide.layoutFrame.size.height
So full frame height = 812.0
, safe area height = 734.0
所以full frame height = 812.0
,safe area height = 734.0
Below is the example where the green view has frame of guide.layoutFrame
下面是绿色视图具有框架的示例 guide.layoutFrame
回答by bsod
Swift 4, 5
斯威夫特 4、5
To pin a view to a safe area anchor using constraints can be done anywhere in the view controller's lifecycle because they're queued by the API and handled after the view has been loaded into memory. However, getting safe-area values requires waiting toward the end of a view controller's lifecycle, like viewDidLayoutSubviews()
.
使用约束将视图固定到安全区域锚点可以在视图控制器生命周期的任何地方完成,因为它们由 API 排队并在视图加载到内存后处理。但是,获取安全区域值需要等待视图控制器生命周期的结束,例如viewDidLayoutSubviews()
.
This plugs into any view controller:
这可以插入任何视图控制器:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let topSafeArea: CGFloat
let 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
}
I prefer this method to getting it off of the window (when possible) because it's how the API was designed and, more importantly, the values are updated during all view changes, like device orientation changes.
我更喜欢这种方法而不是让它离开窗口(如果可能),因为它是 API 的设计方式,更重要的是,在所有视图更改(例如设备方向更改)期间都会更新值。
However, some custom presented view controllers cannot use the above method (I suspect because they are in transient container views). In such cases, you can get the values off of the root view controller, which will always be available anywhere in the current view controller's lifecycle.
但是,一些自定义呈现的视图控制器不能使用上述方法(我怀疑是因为它们在瞬态容器视图中)。在这种情况下,您可以从根视图控制器中获取值,该值在当前视图控制器生命周期中的任何地方始终可用。
anyLifecycleMethod()
guard let root = UIApplication.shared.keyWindow?.rootViewController else {
return
}
let topSafeArea: CGFloat
let bottomSafeArea: CGFloat
if #available(iOS 11.0, *) {
topSafeArea = root.view.safeAreaInsets.top
bottomSafeArea = root.view.safeAreaInsets.bottom
} else {
topSafeArea = root.topLayoutGuide.length
bottomSafeArea = root.bottomLayoutGuide.length
}
// safe area values are now available to use
}
回答by ScottyBlades
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
}
回答by mojtaba al moussawi
All of the answers here are helpful, Thanks to everyone who offered help.
这里的所有答案都很有帮助,感谢所有提供帮助的人。
However as i see that that the safe area topic is a little bit confused which won't appear to be well documented.
但是,正如我所见,安全区域主题有点混乱,似乎没有很好的文档记录。
So i will summarize it here as mush as possible to make it easy to understand safeAreaInsets
, safeAreaLayoutGuide
and LayoutGuide
.
因此,我将在此处尽可能地对其进行总结以使其易于理解safeAreaInsets
,safeAreaLayoutGuide
并且LayoutGuide
。
In iOS 7, Apple introduced the topLayoutGuide
and bottomLayoutGuide
properties in UIViewController
,
They allowed you to create constraints to keep your content from being hidden by UIKit bars like the status, navigation or tab bar
It was possible with these layout guides to specify constraints on content,
avoiding it to be hidden by top or bottom navigation elements (UIKit bars, status bar, nav or tab bar…).
在 iOS 7 中,Apple 引入了topLayoutGuide
和bottomLayoutGuide
属性UIViewController
,它们允许您创建约束以防止您的内容被 UIKit 栏(如状态、导航或标签栏)隐藏 这些布局指南可以指定对内容的约束,避免它被顶部或底部导航元素(UIKit 栏、状态栏、导航栏或标签栏……)隐藏。
So for example if you wanna make a tableView starts from the top screen you have done something like that:
因此,例如,如果您想让 tableView 从顶部屏幕开始,您已经完成了以下操作:
self.tableView.contentInset = UIEdgeInsets(top: -self.topLayoutGuide.length, left: 0, bottom: 0, right: 0)
In iOS 11 Apple has deprecated these properties replacing them with a single safe area layout guide
在 iOS 11 中,Apple 已弃用这些属性,将它们替换为单个安全区域布局指南
Safe area according to Apple
根据 Apple 的安全区域
Safe areas help you place your views within the visible portion of the overall interface. UIKit-defined view controllers may position special views on top of your content. For example, a navigation controller displays a navigation bar on top of the underlying view controller's content. Even when such views are partially transparent, they still occlude the content that is underneath them. In tvOS, the safe area also includes the screen's overscan insets, which represent the area covered by the screen's bezel.
安全区域可帮助您将视图放置在整个界面的可见部分。UIKit 定义的视图控制器可以将特殊视图放置在您的内容之上。例如,导航控制器在底层视图控制器内容的顶部显示导航栏。即使这样的视图是部分透明的,它们仍然会遮挡它们下面的内容。在 tvOS 中,安全区域还包括屏幕的过扫描插图,代表屏幕边框覆盖的区域。
Below, a safe area highlighted in iPhone 8 and iPhone X-series:
下面是 iPhone 8 和 iPhone X 系列中突出显示的安全区域:
The safeAreaLayoutGuide
is a property of UIView
该safeAreaLayoutGuide
是一个属性UIView
To get the height of safeAreaLayoutGuide
:
要获得 的高度safeAreaLayoutGuide
:
extension UIView {
var safeAreaHeight: CGFloat {
if #available(iOS 11, *) {
return safeAreaLayoutGuide.layoutFrame.size.height
}
return bounds.height
}
}
That will return the height of the Arrow in your picture.
这将返回图片中箭头的高度。
Now, what about getting the top "notch" and bottom home screen indicator heights?
现在,如何获得顶部“缺口”和底部主屏幕指示器高度?
Here we will use the safeAreaInsets
这里我们将使用 safeAreaInsets
The safe area of a view reflects the area not covered by navigation bars, tab bars, toolbars, and other ancestors that obscure a view controller's view. (In tvOS, the safe area reflects the area not covered by the screen's bezel.) You obtain the safe area for a view by applying the insets in this property to the view's bounds rectangle. If the view is not currently installed in a view hierarchy, or is not yet visible onscreen, the edge insets in this property are 0.
视图的安全区域反映了导航栏、标签栏、工具栏和其他遮挡视图控制器视图的祖先未覆盖的区域。(在 tvOS 中,安全区域反映了屏幕边框未覆盖的区域。)您可以通过将此属性中的插图应用于视图的边界矩形来获取视图的安全区域。如果视图当前未安装在视图层次结构中,或者尚未在屏幕上可见,则此属性中的边缘插入为 0。
The following will show the unsafe area and there distance from edges on iPhone 8 and one of iPhone X-Series.
下面将显示 iPhone 8 和 iPhone X 系列之一的不安全区域和边缘距离。
Now, if navigation bar added
现在,如果添加了导航栏
So, now how to get the unsafe area height? we will use the safeAreaInset
那么,现在如何获得不安全区域的高度呢?我们将使用safeAreaInset
Here are to solutions however they differ in an important thing,
这是解决方案,但它们在一个重要的事情上有所不同,
First One:
第一:
self.view.safeAreaInsets
That will return the EdgeInsets, you can now access the top and the bottom to know the insets,
这将返回 EdgeInsets,您现在可以访问顶部和底部以了解插入,
Second One:
第二个:
UIApplication.shared.windows.first{override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
let top = view.safeAreaInsets.top
let bottom = view.safeAreaInsets.bottom
}
.isKeyWindow }?.safeAreaInsets
The first one you are taking the view insets, so if there a navigation bar it will be considered , however the second one you are accessing the window's safeAreaInsets so the navigation bar will not be considered
第一个您正在查看视图插入,因此如果有导航栏,它将被考虑,但是第二个您正在访问窗口的 safeAreaInsets,因此不会考虑导航栏
回答by Martin
In iOS 11 there is a method that tells when the safeArea has changed.
在 iOS 11 中,有一种方法可以告知 safeArea 何时发生变化。
`UIApplication.shared.keyWindow`
回答by user1039695
Swift 5, Xcode 11.4
斯威夫特 5,Xcode 11.4
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: { self.safeAreaLayoutGuide.layoutFrame.size.height
.isKeyWindow })
}
}
It will give deprecation warning. ''keyWindow' was deprecated in iOS 13.0: Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes' because of connected scenes. I use this way.
它将给出弃用警告。''keyWindow' 在 iOS 13.0 中已弃用:不应用于支持多个场景的应用程序,因为它会在所有连接的场景中返回一个关键窗口,因为连接的场景。我用这种方式。
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
CGFloat fBottomPadding = window.safeAreaInsets.bottom;
回答by malhal
safeAreaLayoutGuideWhen the view is visible onscreen, this guide reflects the portion of the view that is not covered by navigation bars, tab bars, toolbars, and other ancestor views. (In tvOS, the safe area reflects the area not covered the screen's bezel.) If the view is not currently installed in a view hierarchy, or is not yet visible onscreen, the layout guide edges are equal to the edges of the view.
safeAreaLayoutGuide当视图在屏幕上可见时,该指南反映了未被导航栏、标签栏、工具栏和其他祖先视图覆盖的视图部分。(在 tvOS 中,安全区域反映了屏幕边框未覆盖的区域。)如果视图当前未安装在视图层次结构中,或者尚未在屏幕上可见,则布局指南边缘等于视图的边缘。
Then to get the height of the red arrow in the screenshot it's:
然后要获取屏幕截图中红色箭头的高度,它是:
##代码##回答by Peter
回答by DmitryShapkin
Objective-CWho had the problem when keyWindowis equal to nil. Just put the code above in viewDidAppear(not in viewDidLoad)
Objective-C当keyWindow等于nil时谁有问题。只需将上面的代码放在viewDidAppear 中(不在 viewDidLoad 中)