ios UIView 中的 safeAreaInsets 在 iPhone X 上为 0
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47032855/
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
safeAreaInsets in UIView is 0 on an iPhone X
提问by Joan Cardona
I am updating my app to adapt it for iPhone X. All views work fine by now except one. I have a view controller that presents a custom UIView that covers the whole screen. Before I was using UIScreen.main.bounds
to find out the size of the view before all layout was done (I need it for putting the correct itemSize for a collectionView). I thought that now I could do something like
UIScreen.main.bounds.size.height - safeAreaInsets.bottom
to get the right usable size. The problem is, safeAreaInsets returns (0,0,0,0) trying on an iPhone X (Simulator). Any ideas? In other views, I get the right numbers for safeAreaInsets.
我正在更新我的应用程序以使其适用于 iPhone X。除了一个视图之外,所有视图现在都可以正常工作。我有一个视图控制器,它显示一个覆盖整个屏幕的自定义 UIView。在我UIScreen.main.bounds
用来在所有布局完成之前找出视图的大小之前(我需要它来为 collectionView 放置正确的 itemSize)。我想现在我可以做一些事情
UIScreen.main.bounds.size.height - safeAreaInsets.bottom
来获得正确的可用尺寸。问题是,safeAreaInsets 在 iPhone X(模拟器)上尝试返回 (0,0,0,0)。有任何想法吗?在其他视图中,我得到了 safeAreaInsets 的正确数字。
Thank you!
谢谢!
采纳答案by Joan Cardona
I already figure out the solution: I was doing all the implementation in the init
of the view. safeAreaInsets has the correct size in layoutSubviews()
我已经找到了解决方案:我init
在视图中完成了所有的实现。safeAreaInsets 具有正确的大小layoutSubviews()
回答by Richard West-Soley
I recently had a similar problem where the safe area insets are returning (0, 0, 0, 0) as soon as viewDidLoad is triggered. It seems that they are set fractionally later than the rest of the view loading.
我最近遇到了一个类似的问题,即一旦触发 viewDidLoad,安全区域插入就会返回 (0, 0, 0, 0)。似乎它们的设置比视图加载的其余部分稍晚。
I got round it by overriding viewSafeAreaInsetsDidChangeand doing my layout in that instead:
我通过覆盖viewSafeAreaInsetsDidChange并在其中进行布局来解决它:
override func viewSafeAreaInsetsDidChange() {
// ... your layout code here
}
回答by Rory Prior
I've run into this issue too trying to move up views to make way for the keyboard on the iPhone X. The safeAreaInsets of the main view are always 0, even though I know the subviews have been laid out at this point as the screen has been drawn. A work around I found, as and mentioned above, is to get the keyWindow and check its safe area insets instead.
我也遇到过这个问题,试图向上移动视图以为 iPhone X 上的键盘让路。主视图的 safeAreaInsets 始终为 0,即使我知道此时子视图已布置为屏幕已绘制。如上所述,我发现的一个解决方法是获取 keyWindow 并检查其安全区域插入。
Obj-C:
对象-C:
CGFloat bottomInset = [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom;
Swift:
迅速:
let bottomInset = UIApplication.shared.keyWindow?.safeAreaInsets.bottom
You can then use this value to adjust constraints or view frames as required.
然后,您可以根据需要使用此值调整约束或视图框架。
回答by Shih Ken
I have a view which is a subview inside another view. I found that I can't get safeAreaInsets correctly, it always return 0, in that view on iPhoneX even if I put it in layoutSubviews. The final solution is I use following UIScreen extension to detect safeAreaInsets which can work like a charm.
我有一个视图,它是另一个视图中的子视图。我发现我无法正确获得 safeAreaInsets,它总是返回 0,在 iPhoneX 的那个视图中,即使我把它放在 layoutSubviews 中。最终的解决方案是我使用以下 UIScreen 扩展来检测可以像魅力一样工作的 safeAreaInsets。
extension UIScreen {
func widthOfSafeArea() -> CGFloat {
guard let rootView = UIApplication.shared.keyWindow else { return 0 }
if #available(iOS 11.0, *) {
let leftInset = rootView.safeAreaInsets.left
let rightInset = rootView.safeAreaInsets.right
return rootView.bounds.width - leftInset - rightInset
} else {
return rootView.bounds.width
}
}
func heightOfSafeArea() -> CGFloat {
guard let rootView = UIApplication.shared.keyWindow else { return 0 }
if #available(iOS 11.0, *) {
let topInset = rootView.safeAreaInsets.top
let bottomInset = rootView.safeAreaInsets.bottom
return rootView.bounds.height - topInset - bottomInset
} else {
return rootView.bounds.height
}
}
}
回答by Mars
I try to use "self.view.safeAreaInset" in a view controller. First, it is a NSInsetZero when I use it in the controller's life cycle method "viewDidLoad", then I search it from the net and get the right answer, the log is like:
我尝试在视图控制器中使用“self.view.safeAreaInset”。首先,当我在控制器的生命周期方法“viewDidLoad”中使用它时它是一个NSInsetZero,然后我从网上搜索并得到正确的答案,日志如下:
ViewController loadView() SafeAreaInsets :UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
ViewController viewDidLoad() SafeAreaInsets :UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
ViewController viewWillAppear() SafeAreaInsets :UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
ViewController viewDidLayoutSubviews() SafeAreaInsets :UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0)
ViewController viewDidAppear() SafeAreaInsets :UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0)
so you can choice the right method that you need the safeAreaInset and use it!
所以你可以选择你需要 safeAreaInset 的正确方法并使用它!
回答by ZAFAR007
Swift iOS 11,12,13+
Swift iOS 11、12、13+
var insets : UIEdgeInsets = .zero
override func viewDidLoad() {
super.viewDidLoad()
insets = UIApplication.shared.delegate?.window??.safeAreaInsets ?? .zero
//Or you can use this
insets = self.view.safeAreaInsets
}
回答by fphilipe
I've come across the same problem. In my case the view I'm inserting would be sized correctly after calling view.layoutIfNeeded()
. The view.safeAreaInsets
was set after this, but only the top
value was correct. The bottom value was still 0
(this on an iPhone X).
我遇到了同样的问题。在我的情况下,我插入的视图在调用view.layoutIfNeeded()
. 将view.safeAreaInsets
在此之后设置,但只有top
价值是正确的。底部值仍然是0
(这在 iPhone X 上)。
While trying to figure out at what point the safeAreaInsets
are set correctly, I've added a breakpoint on the view's safeAreaInsetsDidChange()
method. This was being called multiple times, but only when I saw CALayer.layoutSublayers()
in the backtrace the value had been set correctly.
在试图找出safeAreaInsets
正确设置的点时,我在视图的safeAreaInsetsDidChange()
方法上添加了一个断点。这被多次调用,但只有当我CALayer.layoutSublayers()
在回溯中看到该值已正确设置时。
So I've replaced view.layoutIfNeeded()
by the CALayer
's counterpart view.layer.layoutIfNeeded()
, which resulted in the safeAreaInsets
to be set correctly right away, thus solving my problem.
因此,我已替换view.layoutIfNeeded()
为CALayer
对应的view.layer.layoutIfNeeded()
,从而safeAreaInsets
立即正确设置了 ,从而解决了我的问题。
TL;DR
TL; 博士
Replace
代替
view.layoutIfNeeded()
by
经过
view.layer.layoutIfNeeded()
回答by BuLB JoBs
the viewDidAppear(_:) method of the container view controller that extends the safe area of its embedded child view controller to account for the views in .
容器视图控制器的 viewDidAppear(_:) 方法扩展了其嵌入式子视图控制器的安全区域以解释 .
Make your modifications in this method because the safe area insets for a view are not accurate until the view is added to a view hierarchy.
在此方法中进行修改,因为在将视图添加到视图层次结构之前,视图的安全区域插入是不准确的。
override func viewDidAppear(_ animated: Bool) {
if (@available(iOS 11, *)) {
var newSafeArea = view.safeAreaInsets
// Adjust the safe area to accommodate
// the width of the side view.
if let sideViewWidth = sideView?.bounds.size.width {
newSafeArea.right += sideViewWidth
}
// Adjust the safe area to accommodate
// the height of the bottom view.
if let bottomViewHeight = bottomView?.bounds.size.height {
newSafeArea.bottom += bottomViewHeight
}
// Adjust the safe area insets of the
// embedded child view controller.
let child = self.childViewControllers[0]
child.additionalSafeAreaInsets = newSafeArea
}
}
回答by tounaobun
[UIApplication sharedApplication].keyWindow.safeAreaInsets return none zero
回答by Murat Yasar
Just try self.view.safeAreaInsets
instead of UIApplication.shared.keyWindow?.safeAreaInsets
Safe area insets seems to not fill on iOS 11.x.x devices when requested via application keyWindow.
当通过应用程序 keyWindow 请求时,请尝试self.view.safeAreaInsets
而不是UIApplication.shared.keyWindow?.safeAreaInsets
安全区域插图似乎不会在 iOS 11.xx 设备上填充。