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:
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
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
}
}