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

SwiftUI纯原生方案检测iOS设备顶部刘海及安全区域内边距

纯SwiftUI原生方案判断iOS设备顶部刘海

可以通过SwiftUI原生的GeometryReader获取视图安全区域内边距,无需依赖UIKit组件实现刘海判断,核心逻辑是:非刘海设备顶部安全区域内边距为标准状态栏高度(20pt),刘海设备的顶部内边距会大于该值。

实现方式

方式一:全局复用(通过环境变量)

先定义用于传递安全区域的环境键和偏好键:

// 环境键,用于全局获取安全区域内边距
private struct SafeAreaInsetsKey: EnvironmentKey {
    static var defaultValue: EdgeInsets = EdgeInsets()
}

extension EnvironmentValues {
    var safeAreaInsets: EdgeInsets {
        get { self[SafeAreaInsetsKey.self] }
        set { self[SafeAreaInsetsKey.self] = newValue }
    }
}

// 偏好键,用于从GeometryReader传递安全区域数据
private struct SafeAreaInsetsPreferenceKey: PreferenceKey {
    static var defaultValue: EdgeInsets = EdgeInsets()
    
    static func reduce(value: inout EdgeInsets, nextValue: () -> EdgeInsets) {
        value = nextValue()
    }
}

在根视图中注入安全区域信息,并实现判断逻辑:

struct RootView: View {
    @Environment(\.safeAreaInsets) private var safeAreaInsets
    private let standardTopInset: CGFloat = 20 // 非刘海设备状态栏高度
    
    var body: some View {
        VStack {
            Text(hasTopNotch ? "设备存在顶部刘海" : "设备无顶部刘海")
                .font(.title)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        // 通过GeometryReader获取安全区域并传递给环境
        .background(
            GeometryReader { proxy in
                Color.clear
                    .preference(key: SafeAreaInsetsPreferenceKey.self, value: proxy.safeAreaInsets)
            }
        )
        .onPreferenceChange(SafeAreaInsetsPreferenceKey.self) { insets in
            safeAreaInsets = insets
        }
    }
    
    private var hasTopNotch: Bool {
        safeAreaInsets.top > standardTopInset
    }
}

方式二:单视图简化版

如果仅在单个视图中使用,可直接通过GeometryReader读取并判断:

struct ContentView: View {
    private let standardTopInset: CGFloat = 20
    
    var body: some View {
        GeometryReader { proxy in
            Text(proxy.safeAreaInsets.top > standardTopInset ? "存在顶部刘海" : "无顶部刘海")
                .font(.title)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

关键说明

  • 该方案完全基于SwiftUI原生API,未引入任何UIKit代码。
  • 阈值20pt是iOS非刘海设备的标准状态栏高度,刘海设备的顶部安全区域包含状态栏+刘海高度,因此内边距会大于20pt(如iPhone X及以上机型为44pt)。
  • 逻辑适配所有iOS设备,包括带刘海的iPad Pro(顶部内边距为44pt)。

内容的提问来源于stack exchange,提问作者Deepak Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 19:20:00