Android设备适配刘海屏notch hell的safe inset正确使用方法是什么?
Android Safe Inset 正确实现方案
问题原因
你的原有代码仅读取了挖孔区域的安全边距数值,未将数值应用到对应视图的间距配置中,因此不会产生实际效果。同时直接在onAttachedToWindow中读取rootWindowInsets容易出现Insets尚未完成计算返回null的问题,稳定性差。
通用全场景适配方案
该方案兼容状态栏、导航栏、挖孔屏等所有系统边距场景,适配Android 10及以上版本:
1. 配置窗口参数
首先允许应用内容延伸到系统栏区域,否则Insets计算不会生效:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 关闭系统默认的边距适配,由应用自行处理 WindowCompat.setDecorFitsSystemWindows(window, false) setContentView(R.layout.activity_main) // 取布局的根视图 val rootView = findViewById<ViewGroup>(R.id.root) applySafeInsets(rootView) }
2. 实现Insets应用逻辑
使用官方推荐的OnApplyWindowInsetsListener监听Insets计算完成的回调,再将边距应用到视图:
private fun applySafeInsets(view: View) { ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets -> // 获取包含状态栏、导航栏、挖孔区域的全量安全边距 val safeInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) // 将安全边距设置为根视图的padding,避免内容被系统元素遮挡 view.setPadding( safeInsets.left, safeInsets.top, safeInsets.right, safeInsets.bottom ) insets } }
仅适配挖孔屏方案
如果不需要处理状态栏、导航栏的适配,仅需避开挖孔区域,可以单独读取挖孔相关参数:
@RequiresApi(Build.VERSION_CODES.Q) private fun applyCutoutSafeInsets(view: View) { ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets -> insets.displayCutout?.let { cutout -> view.setPadding( cutout.safeInsetLeft, cutout.safeInsetTop, cutout.safeInsetRight, cutout.safeInsetBottom ) } insets } }
注意事项
- 如果不需要给整个根视图设置边距,可以将Insets数值应用到指定的子视图即可,避免影响整体布局
- 低于Android 10的系统没有挖孔屏相关API,无需做适配
- 不要直接在生命周期回调中硬读Insets数值,使用
OnApplyWindowInsetsListener可以保证Insets计算完成后再执行逻辑,兼容性更高
内容的提问来源于stack exchange,提问作者braop
相关产品推荐
相关产品推荐

