draggable2D

Functions summary

Modifier
Modifier.draggable2D(
    state: Draggable2DState,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    startDragImmediately: Boolean,
    onDragStarted: (startedPosition: Offset) -> Unit,
    onDragStopped: (velocity: Velocity) -> Unit,
    reverseDirection: Boolean
)

Configure touch dragging for the UI element in both orientations.

Cmn

Functions

Modifier.draggable2D

fun Modifier.draggable2D(
    state: Draggable2DState,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    startDragImmediately: Boolean = false,
    onDragStarted: (startedPosition: Offset) -> Unit = NoOpOnDragStart,
    onDragStopped: (velocity: Velocity) -> Unit = NoOpOnDragStop,
    reverseDirection: Boolean = false
): Modifier

Configure touch dragging for the UI element in both orientations. The drag distance reported to Draggable2DState, allowing users to react to the drag delta and update their state.

The common common usecase for this component is when you need to be able to drag something inside the component on the screen and represent this state via one float value

If you are implementing dragging in a single orientation, consider using draggable.

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.draggable2D
import androidx.compose.foundation.gestures.rememberDraggable2DState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

// Draw a box that has a a grey background
// with a red square that moves along 300.dp dragging in both directions
val max = 200.dp
val min = 0.dp
val (minPx, maxPx) = with(LocalDensity.current) { min.toPx() to max.toPx() }
// this is the offset we will update while dragging
var offsetPositionX by remember { mutableStateOf(0f) }
var offsetPositionY by remember { mutableStateOf(0f) }

Box(
    modifier =
        Modifier.width(max)
            .height(max)
            .draggable2D(
                state =
                    rememberDraggable2DState { delta ->
                        val newValueX = offsetPositionX + delta.x
                        val newValueY = offsetPositionY + delta.y
                        offsetPositionX = newValueX.coerceIn(minPx, maxPx)
                        offsetPositionY = newValueY.coerceIn(minPx, maxPx)
                    }
            )
            .background(Color.LightGray)
) {
    Box(
        Modifier.offset {
                IntOffset(offsetPositionX.roundToInt(), offsetPositionY.roundToInt())
            }
            .size(50.dp)
            .background(Color.Red)
    )
}
Parameters
state: Draggable2DState

Draggable2DState state of the draggable2D. Defines how drag events will be interpreted by the user land logic.

enabled: Boolean = true

whether or not drag is enabled

interactionSource: MutableInteractionSource? = null

MutableInteractionSource that will be used to emit DragInteraction.Start when this draggable is being dragged.

startDragImmediately: Boolean = false

when set to true, draggable2D will start dragging immediately and prevent other gesture detectors from reacting to "down" events (in order to block composed press-based gestures). This is intended to allow end users to "catch" an animating widget by pressing on it. It's useful to set it when value you're dragging is settling / animating.

onDragStarted: (startedPosition: Offset) -> Unit = NoOpOnDragStart

callback that will be invoked when drag is about to start at the starting position, allowing user to perform preparation for drag.

onDragStopped: (velocity: Velocity) -> Unit = NoOpOnDragStop

callback that will be invoked when drag is finished, allowing the user to react on velocity and process it.

reverseDirection: Boolean = false

reverse the direction of the dragging, so top to bottom dragging will behave like bottom to top and left to right will behave like right to left.