在Jetpack Compose中,如何让Material3的模态底部弹出层不可拖动,同时内部内容仍然可滚动?

移动开发 2026-07-09

描述

我在Jetpack Compose中使用Material3 ModalBottomSheet,并且想在它里面放置一个可滚动的列表。

问题在于,底部弹出层内部的可滚动内容与ModalBottomSheet本身的滑动/拖拽手势似乎存在冲突。当用户在弹出层内部向下滚动或拖拽时,底部弹出层也会跟着移动。

我通过创建自定义的底部弹出层组件解决了这个问题,但如果可能的话,我更愿意避免那种做法。

有没有办法让Material3 ModalBottomSheet 不可拖动,同时仍然允许内部内容滚动?

尝试解决的方法

我尝试使用 confirmValueChange

val sheetState = rememberModalBottomSheetState(
    skipPartiallyExpanded = true,
    confirmValueChange = { newValue ->
        newValue != SheetValue.Hidden
    }
)

ModalBottomSheet(
    sheetState = sheetState,
    onDismissRequest = {},
    dragHandle = null
) {
    Content()
}

这会阻止底部弹出层被隐藏,但并不会禁用拖拽动画本身。底部弹出层仍然可以稍微向下拖动/滑动,然后回弹。

我想要的是完全禁用ModalBottomSheet的滑动/拖拽行为,这样就只有内部的可滚动列表处理垂直手势。

解决方案

要在保持内部内容独立滚动的同时,使Material 3 ModalBottomSheet 不可拖动,应该使用sheetGesturesEnabled参数。
传递 sheetGesturesEnabled = false 会禁用底部弹出层本身的滑动关闭手势,解决手势冲突,并使内部容器(如 LazyColumnverticalScroll)能够完全处理垂直手势。

注:sheetGesturesEnabled 是在 Material 3 v1.4.0-alpha02 中引入的,因此请确保在 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()
    }
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章