Android全屏模式下如何监听状态栏与导航栏的显隐状态?
安卓全屏模式下检测状态栏/导航栏显隐事件方案
实现思路
系统栏显隐时会触发系统UI可见性变化回调,不同安卓版本对应不同的监听API,分别适配即可实现精准检测。
适配方案
方案1:Android 11(API 30及以上)官方推荐方案
使用WindowInsetsAnimation.Callback监听系统栏动画的全生命周期,可拿到实时显隐状态:
// 给Window设置系统栏动画回调 window.decorView.setWindowInsetsAnimationCallback(object : WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) { override fun onPrepare(animation: WindowInsetsAnimation) { super.onPrepare(animation) // 系统栏显隐动画准备开始时触发 } override fun onProgress( insets: WindowInsets, runningAnimations: MutableList<WindowInsetsAnimation> ): WindowInsets { // 动画执行过程中触发,可通过insets判断当前系统栏可见性 val isStatusBarVisible = insets.isVisible(WindowInsets.Type.statusBars()) val isNavBarVisible = insets.isVisible(WindowInsets.Type.navigationBars()) // 此处可添加自定义逻辑,比如同步显隐自定义标题栏 return insets } override fun onEnd(animation: WindowInsetsAnimation) { super.onEnd(animation) // 动画结束时触发,可拿到最终的显隐状态 val finalInsets = window.decorView.rootWindowInsets val finalStatusVisible = finalInsets?.isVisible(WindowInsets.Type.statusBars()) == true val finalNavVisible = finalInsets?.isVisible(WindowInsets.Type.navigationBars()) == true } })
方案2:低版本兼容方案(API 16到API 29)
使用兼容性良好的View.OnSystemUiVisibilityChangeListener监听可见性变化:
window.decorView.setOnSystemUiVisibilityChangeListener { visibility -> // 判断状态栏是否可见 val isStatusBarVisible = (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 // 判断导航栏是否可见 val isNavBarVisible = (visibility and View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0 if (isStatusBarVisible || isNavBarVisible) { // 系统栏被临时唤出 } else { // 系统栏已重新隐藏 } }
补充说明
- 若需要实现和系统Actionbar一致的同步显隐效果,可在回调中同步修改自定义标题栏的可见性/顶部边距即可。
- 若需要系统栏临时唤出后自动恢复隐藏,可在结束回调中添加延迟任务,重新设置你原有代码里的全屏flag即可。
内容的提问来源于stack exchange,提问作者Bencri
相关产品推荐
相关产品推荐

