如何在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
相关产品推荐
相关产品推荐

