You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在OpenGL应用中如何获取iPhone X的刘海尺寸与安全区域大小?

解决GLKView全屏游戏获取安全区域/刘海尺寸的问题

我刚好处理过类似的GLKView全屏游戏适配异形屏的问题,你遇到的safeAreaInsets返回0的情况,大概率是获取时机不对或者方法没选对,硬编码尺寸确实不是长久之计,下面给你详细的解决方案:

为什么之前的方法返回0?

你从keyWindow或safeAreaLayoutGuide拿到的Insets为0,通常是因为在视图还没完成布局时就调用了获取代码(比如在viewDidLoad里)。这时候GLKView还没被添加到window,或者window还没完成首次布局,系统还没计算出正确的安全区域值。

正确的获取方式(无需布局系统)

1. 选对获取时机

必须在视图布局完成后再获取安全区域,推荐在GLKViewController的viewDidLayoutSubviews方法里操作,或者GLKView的layoutSubviews方法中:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    self.updateSafeAreaInsets()
}

2. 获取安全区域Insets(iOS 11+)

从GLKView所在的window中获取safeAreaInsets,这是最可靠的方式,能直接拿到像素/点单位的数值:

@available(iOS 11.0, *)
private func updateSafeAreaInsets() {
    // 获取当前view所在window的安全区域
    guard let window = self.view.window else { return }
    let safeInsets = window.safeAreaInsets
    
    // 打印查看数值(竖屏时:非刘海机型top=20,刘海机型top=44;横屏时左右会有对应Insets)
    print("安全区域 - Top: \(safeInsets.top), Bottom: \(safeInsets.bottom), Left: \(safeInsets.left), Right: \(safeInsets.right)")
    
    // 用这些值调整游戏对象和UI:
    // 例如,顶部UI的起始y坐标设为safeInsets.top,避免被刘海/灵动岛遮挡
    // 底部UI的起始y坐标设为UIScreen.main.bounds.height - safeInsets.bottom - 你的UI高度
}

3. 单独计算刘海/灵动岛尺寸

如果你需要单独获取刘海(或灵动岛)的高度,可通过安全区域顶部值与状态栏高度的差值计算:

@available(iOS 11.0, *)
private func getNotchHeight() -> CGFloat {
    guard let window = self.view.window else { return 0 }
    let safeTop = window.safeAreaInsets.top
    // 获取状态栏高度
    let statusBarHeight = UIApplication.shared.statusBarFrame.height
    // 刘海高度 = 安全区域顶部高度 - 状态栏基础高度(非刘海机型状态栏为20pt,差值为0)
    return safeTop - statusBarHeight
}

4. iOS版本兼容

如果你的游戏需要支持iOS 10及以下,直接默认安全区域为整个屏幕即可,因为这些机型没有异形屏:

private func setupGameLayout() {
    var topInset: CGFloat = 0
    var bottomInset: CGFloat = 0
    
    if #available(iOS 11.0, *) {
        guard let window = self.view.window else { return }
        let safeInsets = window.safeAreaInsets
        topInset = safeInsets.top
        bottomInset = safeInsets.bottom
    }
    
    // 用topInset和bottomInset来布局你的游戏元素
}

关键提醒

  • 不要硬编码任何机型的尺寸,包括刘海高度,因为不同机型(比如iPhone 14 Pro的灵动岛)的安全区域值会有差异,直接用safeAreaInsets能自动适配所有异形屏。
  • 确保GLKView是全屏的(frame等于屏幕bounds),否则window的safeAreaInsets可能和view的不一致。

内容的提问来源于stack exchange,提问作者mr.dog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:12:28