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 }
额外优化建议
- 在
setScaleWH里,建议用boundingRect.width()和boundingRect.height()来计算缩放比例,比直接用right和bottom更准确:
private fun setScaleWH() { scaleWidth = boundingRect.width().toFloat() / drawingViewBitmap.width.toFloat() scaleHeight = boundingRect.height().toFloat() / drawingViewBitmap.height.toFloat() }
onSizeChanged里的requestLayout()可以去掉,因为onSizeChanged已经是布局变化后的回调,不需要再次请求布局。
内容的提问来源于stack exchange,提问作者thebluepandabear
相关产品推荐
相关产品推荐

