How to make Material3 ModalBottomSheet non-draggable while keeping internal content scrollable in Jetpack Compose?
I am using Material3 ModalBottomSheet in Jetpack Compose and I want to place a scrollable list inside it.
The problem is that there seems to be a gesture conflict between the scrollable content inside the bottom sheet and the swipe/drag gesture of the ModalBottomSheet itself. When the user scrolls or drags down inside the sheet, the bottom sheet starts moving as well.
I was able to solve this by creating a custom bottom sheet component, but I would prefer to avoid that if possible.
Is there any way to make Material3 ModalBottomSheet non-draggable, while still allowing the content inside it to be scrollable?
I tried using confirmValueChange:
val sheetState = rememberModalBottomSheetState( skipPartiallyExpanded = true, confirmValueChange = { newValue -> newValue != SheetValue.Hidden } ) ModalBottomSheet( sheetState = sheetState, onDismissRequest = {}, dragHandle = null ) { Content() }
This prevents the sheet from being hidden, but it does't disable the drag animation itself. The sheet can still be dragged/swiped down slightly and then snaps back.
What I want is to completely disable the swipe/drag behavior of ModalBottomSheet, so that only the internal scrollable list handles vertical gestures.
To make the Material 3 ModalBottomSheet non-draggable while preserving the independent scrolling of its internal content, you should use the sheetGesturesEnabled parameter.
Passing sheetGesturesEnabled = false disables the top-level swipe-to-dismiss behavior on the bottom sheet itself, resolving the gesture conflict and allowing internal containers (like a LazyColumn or a verticalScroll) to fully handle vertical gestures.
Note: sheetGesturesEnabled was added in Material 3 v1.4.0-alpha02 so you should ensure you're using the latest version in the Compose BOM
@Composable
fun NonDraggableBottomSheet(
onDismissRequest: () -> Unit
) {
val sheetState = rememberModalBottomSheetState(
skipPartiallyExpanded = true
)
ModalBottomSheet(
onDismissRequest = onDismissRequest,
sheetState = sheetState,
// This disables the outer swipe-to-dismiss drag behavior
sheetGesturesEnabled = false,
dragHandle = null
) {
// Your scrollable internal content
Content()
}
}
Mofe Ejegi