简体   繁体   English

在 Jetpack Compose 上检测滑动方向

[英]Detect swipe direction on Jetpack Compose

I'm trying to detect swipe direction in Compose.我正在尝试检测 Compose 中的滑动方向。 I'm using the draggable modifier for this.我为此使用了可拖动修饰符。 But draggable allows only one direction to detect (Vertical or Horizontal).但是 draggable 只允许检测一个方向(垂直或水平)。 I want to detect swipes for all directions (left, right, up, down).我想检测所有方向(左、右、上、下)的滑动。 Can anyone help me how can I do this?谁能帮我我该怎么做? Thanks!谢谢!

With 1.0.0 (tested with 1.0.0-rc01 ) you can use the pointerInput modifier controlling the dragging gesture with the detectDragGestures function.使用1.0.0 (使用1.0.0-rc01测试),您可以使用pointerInput修饰符控制拖动手势与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
                }
            }
    )
}

Modifier.dragGestureFilter detects dragging in any direction. Modifier.dragGestureFilter检测任何方向的拖动。 Pass an instance of DragObserver and override onDrag .传递DragObserver的实例并覆盖onDrag Here you can detect the swipe direction based on the Offset .在这里,您可以根据Offset检测滑动方向。 This object has x and y values, which are positive or negative based on the direction.此 object 具有xy值,根据方向为正或负。

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 .要实际移动 object,您必须使用在onDrag中更新的值应用Modifier.offset

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
                        }
                    }
                }
            )
        
)

To complement the answers from @Gabriel and @J-Abdo I did something similar based on this answers, for me I need only left/right swipe and I added an "offset" with the min lenght that I want to be considered "swipe"为了补充@Gabriel 和@J-Abdo 的答案,我根据这个答案做了类似的事情,对我来说,我只需要向左/向右轻扫,我添加了一个“偏移量”,其中包含我希望被视为“轻扫”的最小长度

 BoxWithConstraints {
        var offsetX by remember { mutableStateOf(0f) }
        val minSwipeOffset by remember {
            mutableStateOf(
                constraints.maxWidth / 4
            )
        }
        Box(
            Modifier
                .fillMaxSize()
                .pointerInput(Unit) {
                    detectDragGestures(
                        onDrag = { change, dragAmount ->
                            change.consume()
                            val (x, y) = dragAmount
                            offsetX += dragAmount.x

                        },
                        onDragEnd = {

                            when {
                                (offsetX < 0F && abs(offsetX) > minSwipeOffset) -> {
                                    SwipeDirection.Left
                                }
                                (offsetX > 0 && abs(offsetX) > minSwipeOffset) -> {
                                    SwipeDirection.Right
                                }
                                else -> null

                            }?.let(onSwipe)
                            offsetX = 0F
                        }
                    )
                }) {
        }
    }

and I'm using just a sealed class for the directions我只使用一个密封类来获取指示


sealed class SwipeDirection {
    object Left : SwipeDirection()
    object Right : SwipeDirection()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM