'Detect swipe direction on Jetpack Compose

I'm trying to detect swipe direction in Compose. I'm using the draggable modifier for this. But draggable allows only one direction to detect (Vertical or Horizontal). I want to detect swipes for all directions (left, right, up, down). Can anyone help me how can I do this? Thanks!



Solution 1:[1]

Modifier.dragGestureFilter detects dragging in any direction. Pass an instance of DragObserver and override onDrag. Here you can detect the swipe direction based on the Offset. This object has x and y values, which are positive or negative based on the direction.

Here's what your code could look like:

Box(
  Modifier.dragGestureFilter(
    dragObserver = object : DragObserver() {
      override fun onDrag(dragDistance: Offset): Offset {
        val (x, y) = dragDistance
        when {
          x > 0 -> { /* right */ }
          x < 0 -> { /* left */ }
        }
        when {
          y > 0 -> { /* down */ }
          y < 0 -> { /* up */ }
        }
      }
    }
  )
)

To actually move the object, you would have to apply Modifier.offset with values that are updated in onDrag.

Solution 2:[2]

With 1.0.0 you can use the pointerInput modifier controlling the dragging gesture with the detectDragGestures function.

Something like:

Box(modifier = Modifier.fillMaxSize()) {
    var offsetX by remember { mutableStateOf(0f) }
    var offsetY by remember { mutableStateOf(0f) }

    Box(
        Modifier
            .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
            .size(100.dp, 100.dp)
            .background(Color.Blue)
            .pointerInput(Unit) {
                detectDragGestures { change, dragAmount ->
                    change.consumeAllChanges()

                    val (x,y) = dragAmount
                    when {
                        x > 0 ->{ /* right */ }
                        x < 0 ->{ /* left */ }
                    }
                    when {
                        y > 0 -> { /* down */ }
                        y < 0 -> { /* up */ }
                    }

                    offsetX += dragAmount.x
                    offsetY += dragAmount.y
                }
            }
    )
}

Solution 3:[3]

This is a more modified way to get the direction without conflict horizontal swipes with vertical swipes, and to make sure to return the direction after the user end swiping.

var direction by remember { mutableStateOf(-1)}

Box(
    modifier = Modifier
        .pointerInput(Unit) {
            detectDragGestures(
                onDrag = { change, dragAmount ->
                    change.consumeAllChanges()

                    val (x, y) = dragAmount
                    if(abs(x) > abs(y)){
                        when {
                            x > 0 -> {
                                //right
                                direction = 0
                            }
                            x < 0 -> {
                                // left
                                direction = 1
                            }
                        }
                    }else{
                        when {
                            y > 0 -> {
                                // down
                                direction = 2
                            }
                            y < 0 -> {
                                // up
                                direction = 3
                            }
                        }
                    }

                },
                onDragEnd = {
                    when (direction){
                        0 -> {
                            //right swipe code here }
                        1 -> {
                            // left swipe code here
                        }
                        2 -> {
                            // down swipe code here
                        }
                        3 -> {
                            // up swipe code here
                        }
                    }
                }
            )
        
)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Noah
Solution 2
Solution 3 J-Abdo