Search code examples
androidmaterial-components-androidbottomsheetdialogfragment

Modal Bottom sheet not becoming full screen


I want a modal bottom sheet to fill the entire screen minus a custom offset. This is my code:

<style name="Widget.App.HuddlePostBottomSheet" parent="ThemeOverlay.MaterialComponents.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/Widget.App.HuddlePostBottomSheet.Modal</item>
</style>

<style name="Widget.App.HuddlePostBottomSheet.Modal" parent="Widget.MaterialComponents.BottomSheet.Modal">
    <item name="backgroundTint">@color/colorSurface</item>
    <item name="shapeAppearance">@style/ShapeAppearance.App.HuddlePostBottomSheet</item>
    <item name="behavior_fitToContents">false</item>
    <item name="behavior_skipCollapsed">false</item>
    <item name="behavior_draggable">true</item>
    <item name="behavior_expandedOffset">120dp</item>
    <item name="shouldRemoveExpandedCorners">false</item>
</style>

And I have overriden the onCreateDialog() method in the fragment:

class HuddlePostFragment : BottomSheetDialogFragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setStyle(STYLE_NORMAL,R.style.Widget_App_HuddlePostBottomSheet)
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog =  super.onCreateDialog(savedInstanceState)
        if (dialog is BottomSheetDialog) {
            dialog.behavior.apply {
                isFitToContents = false
                state = BottomSheetBehavior.STATE_EXPANDED
            }
        }
        return dialog
    }
}

This is my layout:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">


    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        // UI goes here

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

With this, I expect the layout to fill the expanded bottom sheet, but what I get is this:

enter image description here

I noticed in the layout inspector that the FrameLayout that holds the bottom sheet is still wrap_content. Is there a way to fix this?

I saw some answers suggest using findViewById() to get the FrameLayout, but I don't want to do that because the id might change in the future


Solution

  • You'd set the bottom sheet height to MATCH_PARENT programmatically during fragment lifecycle onViewCreated() or onStart() callbacks:

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        val parentLayout =
            (dialog as BottomSheetDialog)
                .findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
    
        parentLayout?.let { bottomSheet ->
        
            // set the bottom sheet height to match_parent
            val layoutParams = bottomSheet.layoutParams
            layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT
            bottomSheet.layoutParams = layoutParams
    
        }
    }
    

    This won't affect the offset value defined in the BottomSheetDialogFragment style.


    Edit

    I am just a little bit apprehensive of the com.google.android.material.R.id.design_bottom_sheet. Is there a cleaner way to do it? I checked the github issues section but I couldnt find any discussion about exposing a setting to change it.

    I'm not sure if they would do that for some reason; if they did so, that would dramatically change the lives of many developers :). Anyway, you'd use the view parameter passed in the onViewCreated instead:

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
         (view.parent as View).layoutParams.apply {
              height = WindowManager.LayoutParams.MATCH_PARENT
         }
    }