You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jetpack Compose中独立检测两个拖拽手势?

解决Compose中双指独立拖拽检测问题

你的问题出在detectDragGestures本身只支持单指拖拽追踪,它会锁定第一个按下的指针,后续手指按下不会触发新的onDragStart。要实现双指分别控制飞机,需要改用detectPointerGestures手动管理每个指针的状态。

以下是修改后的代码示例:

@Composable
fun AirRacesContent() {
    var boxWidth by remember { mutableStateOf(0.dp) }
    var boxHeight by remember { mutableStateOf(0.dp) }
    val density = LocalDensity.current
    val TAG = "AirRacesContent"

    // 记录每个指针对应的飞机偏移量,pointerId作为唯一标识
    val planeOffsets = remember { mutableStateMapOf<Long, Offset>() }
    // 维护两架飞机的当前位置
    val plane1Position = remember { mutableStateOf(Offset.Zero) }
    val plane2Position = remember { mutableStateOf(Offset.Zero) }

    Box(modifier = Modifier
        .fillMaxSize()
        .paint(painterResource(id = R.drawable.background), contentScale = ContentScale.FillBounds)
        .onSizeChanged { size ->
            with(density) {
                boxWidth = size.width.toDp()
                boxHeight = size.height.toDp()
            }
            // 初始化两架飞机的初始位置(像素级)
            plane1Position.value = Offset(
                (boxWidth / 4 - 70.dp/2).toPx(),
                (boxHeight * 8 / 10).toPx()
            )
            plane2Position.value = Offset(
                (boxWidth / 4 * 3 - 70.dp/2).toPx(),
                (boxHeight * 8 / 10).toPx()
            )
        }
        .pointerInput(Unit) {
            detectPointerGestures(
                onDown = { change ->
                    val pointerId = change.id
                    // 根据按下位置分配对应飞机的初始位置
                    val targetPosition = if (change.position.x < size.width / 2) {
                        plane1Position.value
                    } else {
                        plane2Position.value
                    }
                    planeOffsets[pointerId] = targetPosition
                    Log.d(TAG, "手指按下: $pointerId, 位置: ${change.position}")
                },
                onDrag = { change, dragAmount ->
                    val pointerId = change.id
                    planeOffsets[pointerId]?.let { currentOffset ->
                        val newOffset = currentOffset + dragAmount
                        planeOffsets[pointerId] = newOffset
                        // 更新对应飞机的位置
                        if (change.position.x < size.width / 2) {
                            plane1Position.value = newOffset
                        } else {
                            plane2Position.value = newOffset
                        }
                    }
                },
                onUp = { change ->
                    planeOffsets.remove(change.id)
                }
            )
        }) {
        val planeSize = 70.dp
        Image(
            painter = painterResource(id = R.drawable.plane1),
            contentDescription = "玩家1的飞机",
            modifier = Modifier.size(planeSize)
                .offset {
                    IntOffset(
                        plane1Position.value.x.toInt(),
                        plane1Position.value.y.toInt()
                    )
                }
        )

        Image(
            painter = painterResource(id = R.drawable.plane2),
            contentDescription = "玩家2的飞机",
            modifier = Modifier.size(planeSize)
                .offset {
                    IntOffset(
                        plane2Position.value.x.toInt(),
                        plane2Position.value.y.toInt()
                    )
                }
        )
    }
}

关键改动说明:

  • 替换detectDragGestures为detectPointerGestures,它能捕获所有指针的按下、拖拽、抬起事件
  • 用mutableStateMapOf<Long, Offset>记录每个指针的拖拽状态,pointerId是区分不同手指的唯一标识
  • 通过按下位置的x坐标区分左右区域,确保手指对应到正确的飞机进行控制
  • 使用offset { IntOffset(...) }实现像素级的动态偏移,适配拖拽操作的精度需求

内容的提问来源于stack exchange,提问作者Alyona

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 03:07:45