[FR]: longPressDraggable Support for onLongPress Event & onClick Event
This library is amazing!
However, I have a requirement for longPressDraggable where I need to respond to onLongPress first before responding to onDragStarted().
Currently, the internal implementation of longPressDraggable intercepts the long press event. Could you add a new function or an interface like onLongPress: () -> Unit = { }?
Hmm can't you just use onDragStart? It should be called right after a long press
longPressDraggable uses detectDragGesturesAfterLongPress which doesn't have a separate onLongPress so I don't know how I can add one easily.
suspend fun PointerInputScope.detectDragGesturesAfterLongPress(
onDragStart: (Offset) -> Unit = { },
onDragEnd: () -> Unit = { },
onDragCancel: () -> Unit = { },
onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit
)
Or are you suggesting something like making onDragStarted a suspend function where dragging wouldn't start until it returns?
Yes, this approach can solve the issue of missing the onLongPress event. However, my requirement also includes an onClick event, which I use to trigger navigation actions.
When I attempted to chain .clickable() with longPressDraggable() using Modifier, I found that the .clickable() event would be triggered after the drag ends, leading to unexpected navigation behavior.
To address this, I adjusted the code to use awaitPointerEventScope for gesture detection, and I submitted a PR to demonstrate this functionality: https://github.com/Calvin-LL/Reorderable/pull/56.
Would you be willing to allow me to continue contributing to this feature request?
Alternatively, would you consider changing the internal modifier in ReorderableLazyCollection.kt to open, so that users of the library can override it themselves?
First off, this library was a godsend. THANK YOU TO EVERYONE INVOLVED π.
I have a similar requirement for detecting clicks vs long presses vs dragged.
Situations I need to handle: β The item is clickable, which works currently β The item should be dragged on long press, this currently works by long pressing and then dragging π‘The item should be selectable on long press.
This currently does not work because I don't have a hook to detect that the item was long pressed but not moved. For instance, if the item was long pressed but ended back up in the same location, then I can treat it as selected in my UI. The onMove routine doesn't fire if the item is over it's original square, so I can't use that (ie, from == to). The onDragStarted handler gives me startedPosition, but without final position on onDragStopped I can't determine where it ended up.
Is that possible to add startedPosition and finalPosition (or just finalPosition) on the onDragStopped handler please?
You can handle events before they pass to longPressDraggable.
However, you should not do a consume() as this will cause the drag event to be cancelled.
val touchSlop = LocalViewConfiguration.current.touchSlop
var isOverSlop by remember { mutableStateOf(false) }
Modifier
.longPressDraggableHandle()
.pointerInput(Unit) {
awaitEachGesture {
while (true) {
val down = awaitFirstDown()
val longPress = awaitLongPressOrCancellation(down.id) ?: return@awaitEachGesture
drag(longPress.id) { change ->
if (isOverSlop) return@drag
val dragMovement = longPress.position - change.position
if (maxOf(abs(dragMovement.x), abs(dragMovement.y)) > touchSlop) {
isOverSlop = true
}
}
// After the drag event is over
if (!isOverSlop) {
onLongPress()
}
isOverSlop = false
}
}
}
v2.5.0 has dragGestureDetector in Modifier.draggableHandle now. It should be possible to add custom gestures with it.
Legend ππ
Thanks a lot for real!
Legend indeed ππ»