---
title: "detectDragGestures"
description: "Gesture detector that waits for pointer down and touch slop in any direction and then calls
[onDrag] for each drag event. It follows the touch slop detection of
[awaitTouchSlopOrCancellation] but will consume the position change automatically once the touch
slop has been crossed. @see [detectDragGestures] with orientation lock for a fuller set of
capabilities.

[onDragStart] called when the touch slop has been passed and includes an [Offset] representing
the last known pointer position relative to the containing element. The [Offset] can be outside
the actual bounds of the element itself meaning the numbers can be negative or larger than the
element bounds if the touch target is smaller than the
[ViewConfiguration.minimumTouchTargetSize].

[onDragEnd] is called after all pointers are up and [onDragCancel] is called if another gesture
has consumed pointer input, canceling this gesture.

Example Usage:"
type: "function"
---

<div class='type'>Function</div>


<a id='references'></a>
<div class='sourceset sourceset-common'>Common</div>


```kotlin
suspend fun PointerInputScope.detectDragGestures(
    onDragStart: (Offset) -> Unit = {},
    onDragEnd: () -> Unit = {},
    onDragCancel: () -> Unit = {},
    onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit,
) =
    detectDragGestures(
        onDragStart = { _, slopTriggerChange, _ -> onDragStart(slopTriggerChange.position) },
        onDragEnd = { onDragEnd.invoke() },
        onDragCancel = onDragCancel,
        shouldAwaitTouchSlop = { true },
        orientationLock = null,
        onDrag = onDrag,
    )
```


Gesture detector that waits for pointer down and touch slop in any direction and then calls
`onDrag` for each drag event. It follows the touch slop detection of
`awaitTouchSlopOrCancellation` but will consume the position change automatically once the touch
slop has been crossed. @see `detectDragGestures` with orientation lock for a fuller set of
capabilities.

`onDragStart` called when the touch slop has been passed and includes an `Offset` representing
the last known pointer position relative to the containing element. The `Offset` can be outside
the actual bounds of the element itself meaning the numbers can be negative or larger than the
element bounds if the touch target is smaller than the
`ViewConfiguration.minimumTouchTargetSize`.

`onDragEnd` is called after all pointers are up and `onDragCancel` is called if another gesture
has consumed pointer input, canceling this gesture.

Example Usage:



<div class='sourceset sourceset-common'>Common</div>


```kotlin
suspend fun PointerInputScope.detectDragGestures(
    orientationLock: Orientation?,
    onDragStart:
        (
            down: PointerInputChange, slopTriggerChange: PointerInputChange, overSlopOffset: Offset,
        ) -> Unit =
        { _, _, _ ->
        },
    onDragEnd: (change: PointerInputChange) -> Unit = {},
    onDragCancel: () -> Unit = {},
    shouldAwaitTouchSlop: () -> Boolean = { true },
    onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit,
)
```


A Gesture detector that waits for pointer down and touch slop in the direction specified by
`orientationLock` and then calls `onDrag` for each drag event. It follows the touch slop
detection of `awaitTouchSlopOrCancellation` but will consume the position change automatically
once the touch slop has been crossed, the amount of drag over the touch slop is reported as the
first drag event `onDrag` after the slop is crossed. If `shouldAwaitTouchSlop` returns true the
touch slop recognition phase will be ignored and the drag gesture will be recognized
immediately.The first `onDrag` in this case will report an `Offset.Zero`.

`onDragStart` is called when the touch slop has been passed and includes an `Offset` representing
the last known pointer position relative to the containing element as well as the initial down
event that triggered this gesture detection cycle. The `Offset` can be outside the actual bounds
of the element itself meaning the numbers can be negative or larger than the element bounds if
the touch target is smaller than the `ViewConfiguration.minimumTouchTargetSize`.

`onDragEnd` is called after all pointers are up with the event change of the up event and
`onDragCancel` is called if another gesture has consumed pointer input, canceling this gesture.


Example Usage:

#### Parameters

| | |
| --- | --- |
| orientationLock | Optionally locks detection to this orientation, this means, when this is provided, touch slop detection and drag event detection will be conditioned to the given orientation axis. `onDrag` will still dispatch events on with information in both axis, but if orientation lock is provided, only events that happen on the given orientation will be considered. This also means that if no event in the orientation is detected we will not dispatch `onDrag` calls. If no value is provided (i.e. null) touch slop and drag detection will happen on an "any" orientation basis, that is, touch slop will be detected if crossed in either direction and drag events will be dispatched if present in either direction. |
| onDragStart | A lambda to be called when the drag gesture starts, it contains information about the last known `PointerInputChange` relative to the containing element and the post slop delta, slopTriggerChange. It also contains information about the down event where this gesture started and the overSlopOffset. |
| onDragEnd | A lambda to be called when the gesture ends. It contains information about the up `PointerInputChange` that finished the gesture. |
| onDragCancel | A lambda to be called when the gesture is cancelled either by an error or when it was consumed. |
| shouldAwaitTouchSlop | Indicates if touch slop detection should be skipped. |
| onDrag | A lambda to be called for each delta event in the gesture. It contains information about the `PointerInputChange` and the movement offset. |




## Code Examples
### DetectDragGesturesSample
```kotlin
@Composable
fun DetectDragGesturesSample() {
    val offsetX = remember { mutableStateOf(0f) }
    val offsetY = remember { mutableStateOf(0f) }
    var size by remember { mutableStateOf(Size.Zero) }
    Box(Modifier.fillMaxSize().onSizeChanged { size = it.toSize() }) {
        Box(
            Modifier.offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
                .size(50.dp)
                .background(Color.Blue)
                .pointerInput(Unit) {
                    detectDragGestures { _, dragAmount ->
                        val original = Offset(offsetX.value, offsetY.value)
                        val summed = original + dragAmount
                        val newValue =
                            Offset(
                                x = summed.x.coerceIn(0f, size.width - 50.dp.toPx()),
                                y = summed.y.coerceIn(0f, size.height - 50.dp.toPx()),
                            )
                        offsetX.value = newValue.x
                        offsetY.value = newValue.y
                    }
                }
        )
    }
}
```

