iOS 11以下版本如何指定自定义视图与安全区域的偏移?
iOS 11之前替代
safeAreaInsets的实现方案 嗨,这个问题我太熟悉了!iOS 11之前苹果还没推出safeAreaInsets,我们当时主要靠下面几种方式来实现自定义视图和安全区域的偏移适配:
1. 用UIViewController的topLayoutGuide和bottomLayoutGuide(推荐)
这是iOS 7到iOS 10官方提供的等效方案,本质是UIKit为控制器提供的布局参考对象,用来对应顶部(状态栏+导航栏)和底部(tabBar)的安全区域范围。
Auto Layout场景示例
如果用Auto Layout约束自定义视图,直接把视图的边缘和这两个Guide绑定就行:
// Swift 代码 NSLayoutConstraint.activate([ customView.topAnchor.constraint(equalTo: self.topLayoutGuide.bottomAnchor), customView.bottomAnchor.constraint(equalTo: self.bottomLayoutGuide.topAnchor), customView.leadingAnchor.constraint(equalTo: view.leadingAnchor), customView.trailingAnchor.constraint(equalTo: view.trailingAnchor) ])
// Objective-C 代码 [NSLayoutConstraint activateConstraints:@[ [customView.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor], [customView.bottomAnchor constraintEqualToAnchor:self.bottomLayoutGuide.topAnchor], [customView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [customView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor] ]];
手动计算偏移场景
如果需要直接获取安全区域的高度值,可以读取这两个Guide的length属性:
let topSafeHeight = self.topLayoutGuide.length let bottomSafeHeight = self.bottomLayoutGuide.length
2. 手动计算安全区域高度(适合非Auto Layout场景)
如果你的布局不是用Auto Layout,也可以手动计算各部分的高度:
- 顶部安全区域:状态栏高度 + 导航栏高度(如果控制器包含导航栏的话)
var topSafeHeight: CGFloat = 0 // 获取状态栏高度 topSafeHeight += UIApplication.shared.statusBarFrame.height // 如果有导航栏,加上导航栏高度 if let navBar = navigationController?.navigationBar { topSafeHeight += navBar.frame.height }
- 底部安全区域:直接取tabBar的高度(如果控制器包含tabBar的话)
let bottomSafeHeight = tabBarController?.tabBar.frame.height ?? 0
3. 封装兼容方法(同时支持iOS 11及更早版本)
为了避免代码里到处写版本判断,建议封装一个扩展,让代码更简洁:
extension UIViewController { /// 顶部安全区域偏移 var safeAreaTopInset: CGFloat { if #available(iOS 11.0, *) { return view.safeAreaInsets.top } else { return topLayoutGuide.length } } /// 底部安全区域偏移 var safeAreaBottomInset: CGFloat { if #available(iOS 11.0, *) { return view.safeAreaInsets.bottom } else { return bottomLayoutGuide.length } } }
之后在代码里就可以统一调用self.safeAreaTopInset,不用再操心系统版本啦!
小提醒
- 如果是在子视图里需要获取安全区域偏移,记得通过父控制器来访问
topLayoutGuide/bottomLayoutGuide,或者把偏移值从控制器传递给子视图。 - 手动计算时要注意控制器的层级结构,比如是否嵌套在导航控制器、tabBar控制器中,避免计算错误。
内容的提问来源于stack exchange,提问作者Andrey M.
相关产品推荐
相关产品推荐

