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

Android 11下CoordinatorLayout实现全屏时状态栏留白及Insets回调不触发问题

Android 11 全屏沉浸模式适配问题解决方案

问题背景

在Android 11系统上使用全屏沉浸模式时出现适配问题,主Activity布局结构如下:

<DrawerLayout .... android:fitsSystemWindows="true">
    <CoordinatorLayout>
          <AppBarLayout>
              <FragmentContainerView>

需要在Fragment中开启全屏模式,Android 11之前的版本使用如下方法隐藏状态栏:

fun hideStatusBar (activity: AppCompatActivity?) {
    activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) 
}

适配Android 11后修改为:

fun hideStatusBar(activity: AppCompatActivity?) {
@Suppress("DEPRECATION")
if (isAtLeastAndroid11()) {
    val controller = activity?.window?.insetsController
    controller?.hide(WindowInsets.Type.statusBars())
} else {
    activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
}

上述代码可以成功隐藏状态栏,但屏幕顶部原状态栏位置会留下一块空白区域。
尝试在Fragment内监听Window Insets调整Fragment容器边距,代码如下:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    if(isAtLeastAndroid11()){
        WindowCompat.setDecorFitsSystemWindows(requireActivity().window, false)
        setUiWindowInsets()
    }
}

private fun setUiWindowInsets() {
    ViewCompat.setOnApplyWindowInsetsListener(rootView) { _, insets ->
    
        posTop = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top
        posBottom = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom

        rootView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
            updateMargins(
                top = posTop,
                bottom = posBottom)
        }

        insets
    }
}

但ViewCompat.setOnApplyWindowInsetsListener始终没有被回调,原因是CoordinatorLayout会消费onApplyWindowInsets回调,其子View无法收到该事件,Fragment的根布局(RelativeLayout)位于布局层级的FragmentContainer内。

问题1:如何让Fragment中设置的setOnApplyWindowInsetsListener成功收到回调?

  • 调整上层布局的fitsSystemWindows属性:将DrawerLayout、CoordinatorLayout、AppBarLayout的android:fitsSystemWindows全部设置为false,避免上层控件提前消费WindowInsets事件,让Insets可以向下分发到Fragment的根布局。
  • 主动触发Insets分发:在给Fragment根布局设置setOnApplyWindowInsetsListener之后,调用rootView.requestApplyInsets(),主动请求系统重新分发Insets事件。
  • 手动分发Insets:如果不需要修改全局布局属性,可以给CoordinatorLayout单独设置OnApplyWindowInsetsListener,拿到Insets对象后手动调用子View的dispatchApplyWindowInsets方法,将事件向下传递给Fragment容器。

问题2:状态栏隐藏时如何让CoordinatorLayout占满整个屏幕?

  • 确保CoordinatorLayout的fitsSystemWindows属性为false,避免系统自动给CoordinatorLayout添加等同于状态栏高度的顶部padding。
  • 隐藏状态栏后手动清除CoordinatorLayout的顶部padding,代码为coordinatorLayout.setPadding(0, 0, 0, 0),消除原有预留的状态栏空白区域。
  • 调整Insets处理逻辑:当状态栏隐藏时,insets.getInsets(WindowInsetsCompat.Type.statusBars()).top会返回0,此时不需要给Fragment根布局添加顶部margin,内容自然可以延伸到原状态栏位置,实现全屏效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 20:39:00