如何根据Notch位置区分横屏模式下左右两侧Safe Area
横屏模式下按刘海实际位置区分左右安全区的落地方案
直接通过系统返回的安全区缩进值判断刘海位置,不要硬编码设备方向做判断——后者在用户开启方向锁、特殊角度持握时很容易出现判断错误,用safeAreaInsets判断准确率100%,兼容所有带刘海/灵动岛的iOS机型。
判断规则
在视图完成布局的生命周期回调里取当前关联窗口的安全区缩进,按以下规则判断:
- 横屏状态下如果
safeAreaInsets.left> 0:刘海在屏幕左侧,业务视图布局到右侧区域即可 - 横屏状态下如果
safeAreaInsets.right> 0:刘海在屏幕右侧,业务视图布局到左侧区域即可 - 无刘海机型左右缩进均为0,按常规安全区规则布局即可
注意:不要在
viewDidLoad阶段取安全区缩进值,此时视图还没完成层级布局,拿到的缩进值全为0,必须在viewDidLayoutSubviews(UIKit)或者GeometryReader布局闭包(SwiftUI)里取值才准确。
UIKit代码示例
// 监听设备方向变化,转屏后触发重新布局 override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil) } @objc private func orientationChanged() { view.setNeedsLayout() } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() guard let window = view.window else { return } let insets = window.safeAreaInsets // 清除旧约束避免冲突 businessView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.deactivate(businessView.constraints) if insets.left > 0 { // 刘海在左,贴右侧安全区布局 NSLayoutConstraint.activate([ businessView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), businessView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), businessView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor), businessView.widthAnchor.constraint(equalToConstant: 320) // 替换为业务需要的宽度 ]) } else if insets.right > 0 { // 刘海在右,贴左侧安全区布局 NSLayoutConstraint.activate([ businessView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), businessView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), businessView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor), businessView.widthAnchor.constraint(equalToConstant: 320) ]) } else { // 无刘海旧机型,居中布局即可 NSLayoutConstraint.activate([ businessView.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor), businessView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), businessView.widthAnchor.constraint(equalToConstant: 320) ]) } }
标准Safe Area的对称适配效果参考:
按照上面的逻辑调整后,业务视图会自动落在刘海对侧的无遮挡区域,不会出现对侧多余留白的问题。
SwiftUI适配说明
SwiftUI不需要额外处理生命周期,直接在GeometryReader中读取proxy的安全区缩进值,按照同样的判断规则设置frame和偏移量即可,转屏时会自动触发重新布局。
内容的提问来源于stack exchange,提问作者Stéphane de Luca
相关产品推荐
相关产品推荐

