如何使 Android BottomSheetDialogFragment 出现在系统/手势栏后面?

Posted

技术标签:

【中文标题】如何使 Android BottomSheetDialogFragment 出现在系统/手势栏后面?【英文标题】:How to make an Android BottomSheetDialogFragment appear behind the system / gesture bar? 【发布时间】:2021-10-26 11:34:51 【问题描述】:

有很多解决方案可以在 android 导航栏后面实现绘图,其中一些来自Google itself,但是,没有一个可以开箱即用地在导航/手势栏后面显示底部表单。

完成这一切需要什么?

【问题讨论】:

【参考方案1】:

我们从一个片段开始:

internal open class MyBottomSheetDialogFragment : BottomSheetDialogFragment() 
    private var myDialog: MyBottomSheetDialog? = null

    val dialog: MyBottomSheetDialog
        get() = myDialog ?: error("Dialog not yet created")

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
        MyBottomSheetDialog(requireContext()).also  dialog ->
            this.myDialog = dialog
        

这是对话框的实现:

internal class MyBottomSheetDialog(context: Context) :
    BottomSheetDialog(context, R.style.MyBottomSheetDialogTheme) 

    override fun onAttachedToWindow() 
        super.onAttachedToWindow()

        val window = window
            ?: error("window not attached?!")
        val sheetView = findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
            ?: error("bottom sheet design not found")

        // ensure the navigation buttons / bar is rendered dark for a light sheet background
        // and no, setting android:windowLightNavigationBar=true on the theme does _not_ work
        WindowInsetsControllerCompat(window, sheetView)
            .isAppearanceLightNavigationBars = true

        // as soon as we have the actual insets, move the sheet down below the 
        // navigation area and give it back some padding so its contents are rendered
        // above
        ViewCompat.setOnApplyWindowInsetsListener(sheetView)  _, windowInsets ->
            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
            sheetView.updatePadding(
                bottom = insets.bottom
            )
            sheetView.updateLayoutParams<ViewGroup.MarginLayoutParams> 
                bottomMargin = -insets.bottom
            
            WindowInsetsCompat.CONSUMED
        
    

最后,这是主题:

    <style name="MyBottomSheetDialogTheme" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
        <item name="bottomSheetStyle">@style/MyBottomSheetStyle</item>
        <!-- ATTENTION: BottomSheetDialog needs _both_, this attribute set to true _and_ 
             a (semi)transparent navigation bar color, to enable edge-to-edge mode. -->
        <item name="enableEdgeToEdge">true</item>
        <item name="android:navigationBarColor">@android:color/transparent</item>
        <item name="shapeAppearanceLargeComponent">@style/MyBottomSheetShapeAppearance</item>
    </style>

    <style name="MyBottomSheetStyle" parent="Widget.MaterialComponents.BottomSheet.Modal">
        <item name="android:windowIsFloating">false</item>
        <item name="backgroundTint">@color/the_sheets_background_color</item>
    </style>

    <style name="MyBottomSheetShapeAppearance" parent="ShapeAppearance.MaterialComponents.LargeComponent">
        <item name="cornerFamily">rounded</item>
        <item name="cornerSize">8dp</item>
    </style>

【讨论】:

以上是关于如何使 Android BottomSheetDialogFragment 出现在系统/手势栏后面?的主要内容,如果未能解决你的问题,请参考以下文章

如何使android中对话框的背景透明?

如何在android中使底部导航栏不透明?

如何使 android 活动方向坚持起始值?

如何使AlertDialog List可滚动Android [重复]

如何使 Android 应用程序与 Android Studio 中的所有 6735 Android 设备兼容 [关闭]

如何使 Android BottomNavigationView 背景透明?