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

代码模块化后MotionEvent返回错误光标Y坐标,画线异常排查

问题:模块化后触摸Y坐标异常导致线条绘制位置错误

原本能正常从Box绘制线条到光标位置的代码,拆分模块化后出现问题——MotionEvent返回的光标Y坐标值不正确,导致线条绘制位置偏移。

绘制线条的代码

val positions = remember {
    mutableStateMapOf<Position, Position>()
}
val list = remember {
    mutableStateListOf<PositionRange>()
}
Canvas(modifier = Modifier.fillMaxSize(), onDraw = {
    positions.forEach {
        val startPosition = it.key
        val endPosition = it.value
        if (startPosition.isNotEmpty() && endPosition.isNotEmpty()) {
            this.drawLine(
                Color.Black,
                Offset(startPosition.x, startPosition.y),
                Offset(endPosition.x, endPosition.y),
                10f,
                StrokeCap.Round,
            )
        }
    }
})

获取触摸位置的代码

@Composable
private fun FromBox(
    list: MutableList<PositionRange>,
    onDragLineEvent: (Pair<Position, Position>) -> Unit,
) {
    var startPosition by Position.rememberEmptyPosition()
    var endPosition by Position.rememberEmptyPosition()
    Box(
        modifier = Modifier
            .onGloballyPositioned {
                val size = it.size
                val coords = it.positionInRoot()
                val posRange =
                    PositionRange(coords.toPosition(), size.width.toFloat(), size.height.toFloat())
                startPosition = posRange.getCenter()
                onDragLineEvent(startPosition to endPosition)
            }
            .pointerInteropFilter {
                if (it.pointerCount == 1) {
                    when (it.action) {
                        MotionEvent.ACTION_MOVE -> {
                            val pos = Position(it.x, it.y)
                            list.forEach { posRange ->
                                if (posRange.inRange(pos)) {
                                    val center = posRange.getCenter()
                                    endPosition = endPosition.copy(
                                        x = center.x,
                                        y = center.y
                                    )
                                    onDragLineEvent(startPosition to endPosition)
                                    return@forEach
                                } else {
                                    endPosition = endPosition.copy(x = pos.x, y = pos.y)
                                    onDragLineEvent(startPosition to endPosition)
                                }
                            }
                        }

                        MotionEvent.ACTION_UP,
                        MotionEvent.ACTION_CANCEL,
                        -> {
                            endPosition = Position.EMPTY
                            onDragLineEvent(startPosition to endPosition)
                        }
                    }
                } else {
                    endPosition = Position.EMPTY
                }
                true
            }
    )
}

Position和PositionRange核心函数

fun inRange(position: Position): Boolean {
    val topEnd = Position(startPoint.x + width, startPoint.y)
    val bottomEnd = Position(startPoint.x, startPoint.y + height)
    val endPos = Position(startPoint.x + width, startPoint.y + height)
    return  (position.x >= startPoint.x && position.y >= startPoint.y) &&
            (position.x <= topEnd.x && position.y >= topEnd.y) &&
            (position.x >= bottomEnd.x && position.y <= bottomEnd.y) &&
            (position.x <= endPos.x && position.y <= endPos.y)
}

fun getCenter(): Position {
    return Position(startPoint.x + width / 2, startPoint.y + height / 2)
}

当前错误绘制效果

线条绘制位置错误1
线条绘制位置错误2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 12:10:23