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

Android横屏时BottomSheetDialog为何绘制在导航栏下方被遮挡

问题描述

开发简单Android模态底部弹窗菜单时,竖屏模式下弹窗显示完全正常,但设备旋转至横屏模式后,底部弹窗的底部区域会绘制在导航栏下方,对应位置的内容被隐藏。
复现测试环境:Pixel C平板模拟器,系统API版本为32。

  • 竖屏模式:显示效果正常
    竖屏模式正常效果
  • 横屏模式:弹窗底部内容被隐藏
    横屏模式底部被遮挡效果

本次复现所用示例代码基于Android Studio的「Empty Activity」模板项目创建,实现逻辑参考Material官方文档中Modal Bottom Sheet的开发指引,核心代码如下:

Kotlin核心代码

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.showDialog.setOnClickListener { showBottomSheetDialog() }
    }


    private fun showBottomSheetDialog() {
        val modalBottomSheet = ModalBottomSheet()
        modalBottomSheet.show(supportFragmentManager, ModalBottomSheet.TAG)
    }
}

class ModalBottomSheet : BottomSheetDialogFragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = inflater.inflate(R.layout.bottom_sheet_dialog, container, false)

    companion object {
        const val TAG = "ModalBottomSheet"
    }
}

弹窗布局文件 bottom_sheet_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text_view_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="30dp"
        android:paddingVertical="12dp"
        android:text="First Row"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/text_view_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="30dp"
        android:paddingVertical="12dp"
        android:text="Second Row"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/text_view_3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="30dp"
        android:paddingVertical="12dp"
        android:text="Third Row"
        android:textSize="16sp" />

</LinearLayout>
解决方案

这个问题是Material组件BottomSheetDialogFragment在高版本系统横屏场景下的窗口边距适配bug:弹窗没有自动计算系统导航栏占用的高度,导致内容绘制到导航栏下方。两种可直接落地的修复方案:

方案1:代码层适配窗口insets(推荐,无布局侵入)

在ModalBottomSheet类中重写onStart方法,手动给弹窗根布局添加导航栏高度的底部内边距:

override fun onStart() {
    super.onStart()
    val bottomSheetDialog = dialog as? BottomSheetDialog ?: return
    val bottomSheetContainer = bottomSheetDialog.findViewById<FrameLayout>(
        com.google.android.material.R.id.design_bottom_sheet
    ) ?: return

    ViewCompat.setOnApplyWindowInsetsListener(bottomSheetContainer) { view, insets ->
        val navigationBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
        view.setPadding(
            view.paddingLeft,
            view.paddingTop,
            view.paddingRight,
            navigationBarInsets.bottom
        )
        insets
    }
}

方案2:布局层开启系统边距适配

给弹窗布局的根LinearLayout添加fitsSystemWindows属性,让系统自动为布局预留系统栏占用空间:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:fitsSystemWindows="true">

    <!-- 原有子View内容保持不变 -->

</LinearLayout>

注意:使用方案2需要将项目的Material组件依赖升级到1.6.0及以上版本,低版本Material库在横屏场景下对fitsSystemWindows的适配存在兼容问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 21:09:21