繁体   English   中英

在 Jetpack Compose 上检测滑动方向

[英]Detect swipe direction on Jetpack Compose

我正在尝试检测 Compose 中的滑动方向。 我为此使用了可拖动修饰符。 但是 draggable 只允许检测一个方向(垂直或水平)。 我想检测所有方向(左、右、上、下)的滑动。 谁能帮我我该怎么做? 谢谢!

使用1.0.0 (使用1.0.0-rc01测试),您可以使用pointerInput修饰符控制拖动手势与detectDragGestures function。

就像是:

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检测任何方向的拖动。 传递DragObserver的实例并覆盖onDrag 在这里,您可以根据Offset检测滑动方向。 此 object 具有xy值,根据方向为正或负。

您的代码可能如下所示:

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

要实际移动 object,您必须使用在onDrag中更新的值应用Modifier.offset

这是一种更修改的方式来获取方向,水平滑动与垂直滑动不会发生冲突,并确保在用户结束滑动后返回方向。

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

为了补充@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
                        }
                    )
                }) {
        }
    }

我只使用一个密封类来获取指示


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

暂无
暂无

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

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