背景
我们需要实现纵向滑动的网格列表,同时我们需要实现条目的长按拖拽功能。
问题
当长按后拖拽方向是纵向,则会与纵向滑动事件发生冲突。此时,LazyVerticalGrid就会优先处理纵向滑动,长按拖拽失效。
原因
通过在detectDragGesturesAfterLongPress的回调中添加日志,如下:
Modifier.pointerInput(Unit) {
detectDragGesturesAfterLongPress(
onDragStart = {
Log.d(TAG, "detectDragGesturesAfterLongPress onDragStart")
},
onDragEnd = {
Log.d(TAG, "detectDragGesturesAfterLongPress onDragEnd")
},
onDragCancel = {
Log.d(TAG, "detectDragGesturesAfterLongPress onDragCancel")
},
onDrag = { change, dragAmount ->
Log.d(TAG, "detectDragGesturesAfterLongPress onDrag")
})
})
通过调试发现以下规律:
1. 当可以正常拖拽时,日志如下
2024-05-07 10:05:09.828 detectDragGesturesAfterLongPress onDragStart
2024-05-07 10:05:10.928 detectDragGesturesAfterLongPress onDrag
2024-05-07 10:05:10.943 detectDragGesturesAfterLongPress onDrag
2024-05-07 10:05:11.225 detectDragGesturesAfterLongPress onDrag
2024-05-07 10:05:11.239 detectDragGesturesAfterLongPress onDrag
2024-05-07 10:05:11.428 detectDragGesturesAfterLongPress onDrag
2024-05-07 10:05:11.444 detectDragGesturesAfterLongPress onDrag
2024-05-07 10:05:11.584 detectDragGesturesAfterLongPress onDrag
2024-05-07 10:05:11.613 detectDragGesturesAfterLongPress onDragEnd
2. 当进行纵向拖拽时,日志如下
2024-05-07 10:04:57.589 detectDragGesturesAfterLongPress onDragStart
2024-05-07 10:04:58.402 detectDragGesturesAfterLongPress onDragCancel
通过以上规律,发现当拖拽方向和滑动方向一致时,detectDragGesturesAfterLongPress的onDrag回调并不会执行。所以我个人猜测原因是,Compose框架在这种情况下,并未处理好事件冲突。(欢迎大神们来指教一下,分析一下原因)
解决方法
还好,Compose的LazyVerticalGrid可组合项为我们预留了userScrollEnabled参数,我们通过动态配置该参数,即可解决这个问题。也就是说,在我们在检测到长按事件时,设置userScrollEnabled = false,当拖拽结束时,我们再设置userScrollEnabled = true
@Composable
fun LazyVerticalGrid(
columns: GridCells,
modifier: Modifier = Modifier,
state: LazyGridState = rememberLazyGridState(),
contentPadding: PaddingValues = PaddingValues(0.dp),
reverseLayout: Boolean = false,
verticalArrangement: Arrangement.Vertical =
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
userScrollEnabled: Boolean = true,
content: LazyGridScope.() -> Unit
)