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

Canvas中居中Rect触摸坐标转换错误问题排查

问题解决:触摸坐标转Bitmap像素坐标错误

你的问题核心是没有将View的触摸坐标转换为boundingRect区域内的相对坐标,直接用整个View的坐标除以缩放比例,自然会因为boundingRect居中的偏移导致计算错误。

错误原因分析

你通过canvas.drawBitmap(drawingViewBitmap, null, boundingRect, null)把Bitmap绘制到了View中央的boundingRect区域,但触摸事件的event.x/event.y是相对于整个View左上角的坐标,而非boundingRect的左上角。比如当boundingRect的left是100时,触摸boundingRect左上角的点,event.x是100,这时候直接除以scaleWidth会得到远大于0的数值,对应到Bitmap里的错误位置。

修正后的代码(仅修改onTouchEvent部分)

@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
    // 先判断触摸点是否在boundingRect范围内
    val touchX = event.x
    val touchY = event.y
    if (!boundingRect.contains(touchX.toInt(), touchY.toInt())) {
        // 触摸在绘制区域外,直接返回
        return true
    }

    // 将触摸坐标转换为相对于boundingRect左上角的坐标
    val relativeX = touchX - boundingRect.left
    val relativeY = touchY - boundingRect.top

    // 计算对应的Bitmap像素坐标
    val coordinateX = (relativeX / scaleWidth).toInt()
    val coordinateY = (relativeY / scaleHeight).toInt()

    when (event.action) {
        MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
            if (coordinateX in 0 until drawingViewBitmap.width && coordinateY in 0 until drawingViewBitmap.height) {
                drawingViewBitmap.setPixel(coordinateX, coordinateY, Color.BLACK)
            }
        }

        MotionEvent.ACTION_UP -> {
            drawingViewBitmap.drawTransparent()
        }
    }

    invalidate()

    return true
}

额外优化建议

  1. 在setScaleWH里,建议用boundingRect.width()和boundingRect.height()来计算缩放比例,比直接用right和bottom更准确:
private fun setScaleWH() {
    scaleWidth = boundingRect.width().toFloat() / drawingViewBitmap.width.toFloat()
    scaleHeight = boundingRect.height().toFloat() / drawingViewBitmap.height.toFloat()
}
  1. onSizeChanged里的requestLayout()可以去掉,因为onSizeChanged已经是布局变化后的回调,不需要再次请求布局。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 02:20:37