Compose LazyColumn拖拽排序:替换长按触发或缩短长按等待时长
You can absolutely either speed up the long-press activation delay or implement tap-to-drag directly. Here are two solutions tailored to your needs:
1. Adjust Long Press Activation Duration
The detectDragGesturesAfterLongPress function has a built-in parameter to override the default system long-press delay (usually 500ms). Just pass a shorter value to make drag activation faster:
fun Modifier.dragContainer(dragDropState: DragDropState): Modifier = this .pointerInput(dragDropState) { detectDragGesturesAfterLongPress( longPressTimeoutMillis = 200L, // Custom delay (e.g., 200ms) onDragStart = { offset -> dragDropState.onDragStart(offset) }, onDrag = { change, offset -> change.consume() dragDropState.onDrag(offset = offset) }, onDragEnd = { dragDropState.onDragInterrupted() }, onDragCancel = { dragDropState.onDragInterrupted() } ) }
This is the simplest fix if you just want to speed up the existing interaction without changing the core gesture pattern.
2. Implement Tap-to-Drag (No Long Press)
To activate drag immediately on tap-and-drag, you’ll need a custom pointer handler that distinguishes intentional drags from normal scrolling. We use the system’s touch slop threshold to avoid accidental drag triggers during scrolls:
import androidx.compose.ui.input.pointer.PointerEventKind import androidx.compose.ui.input.pointer.awaitPointerEventScope import androidx.compose.ui.platform.ViewConfiguration fun Modifier.tapToDragContainer(dragDropState: DragDropState): Modifier = this .pointerInput(dragDropState) { val touchSlop = ViewConfiguration.get(this.context).scaledTouchSlop var initialDownPosition: Offset? = null var isDragging = false awaitPointerEventScope { while (true) { val event = awaitPointerEvent() when (event.type) { PointerEventKind.Down -> { initialDownPosition = event.changes.first().position isDragging = false } PointerEventKind.Move -> { initialDownPosition?.let { downPos -> val currentPos = event.changes.first().position val movementDelta = currentPos - downPos // Start drag only if movement exceeds touch slop if (!isDragging && movementDelta.getDistance() >= touchSlop) { dragDropState.onDragStart(downPos) isDragging = true } // Handle ongoing drag if (isDragging) { event.changes.first().consume() dragDropState.onDrag(movementDelta) } } } PointerEventKind.Up, PointerEventKind.Cancel -> { if (isDragging) { dragDropState.onDragInterrupted() } initialDownPosition = null isDragging = false } } } } }
Key Notes:
- Touch Slop: The
scaledTouchSlopvalue ensures drag only starts when the user moves their finger beyond a small threshold, preventing accidental triggers during normal scrolling or taps. - Scroll Conflict: If applying this to the entire list item, it might interfere with LazyColumn’s vertical scrolling. For better UX, consider restricting drag activation to a specific "drag handle" (like a hamburger icon) instead of the whole item.
内容的提问来源于stack exchange,提问作者Hector

