Android30迁移使用WindowInsetsController#hide隐藏状态栏导致内容跳动问题
Android 11+ 使用WindowInsetsController隐藏状态栏内容跳动解决方案
问题根因
旧版FLAG_FULLSCREENAPI会自动让Activity内容布局延伸到状态栏区域,系统不会给根布局自动添加状态栏高度的padding,所以隐藏过程平滑。
使用新WindowInsetsControllerAPI时默认DecorFitsSystemWindows为true,系统会自动给根布局添加和状态栏等高的top padding,隐藏状态栏时padding瞬间消失,就会出现内容向上跳动的视觉异常。
解决步骤
- 第一步:在
onCreate方法setContentView之前,设置布局延伸到系统栏区域,关闭系统自动添加padding的逻辑:
// Kotlin 实现 WindowCompat.setDecorFitsSystemWindows(window, false)
// Java 实现 WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
- 第二步:适配不同系统版本调用对应的全屏逻辑:
// Kotlin 实现 requestWindowFeature(Window.FEATURE_NO_TITLE) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.insetsController?.apply { hide(WindowInsets.Type.statusBars()) // 可选配置:避免边缘滑动拉出状态栏时再次出现布局跳动 systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } } else { @Suppress("DEPRECATION") window.setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN ) }
// Java 实现 requestWindowFeature(Window.FEATURE_NO_TITLE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { WindowInsetsController insetsController = getWindow().getInsetsController(); if (insetsController != null) { insetsController.hide(WindowInsets.Type.statusBars()); insetsController.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); } } else { getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN ); }
可选配置
如果你的界面存在需要避开状态栏的元素(比如自定义标题栏、操作按钮),不要依赖系统自动添加的间距,手动监听WindowInsets动态设置对应View的padding,避免状态栏显示时元素被遮挡:
yourTargetView.setOnApplyWindowInsetsListener { view, insets -> val statusBarTopInset = insets.getInsets(WindowInsets.Type.statusBars()).top view.updatePadding(top = statusBarTopInset) insets }
内容的提问来源于stack exchange,提问作者Lingviston
相关产品推荐
相关产品推荐

