Android Kotlin触摸绘图偏移问题:平板点击与绘图位置不符
解决平板设备上绘图触摸位置偏移问题
问题根源
你手动计算坐标的方式没有考虑ImageView内部的ImageMatrix变换(比如适配不同屏幕密度、缩放模式的实际偏移),模拟器与平板的屏幕参数差异导致手动计算的缩放/偏移值不准确,最终出现触摸点与绘图位置不匹配的情况。
解决方案
用ImageView自带的imageMatrix转换触摸坐标到图片实际坐标,同时确保图片可修改:
1. 修改触摸事件处理函数
替换手动计算坐标的逻辑,使用imageMatrix.mapPoints()完成坐标映射:
private fun handleTouch(event: MotionEvent): Boolean { val drawable = drawable ?: return false if (drawable !is BitmapDrawable) return false val bitmap = drawable.bitmap val matrix = imageMatrix val touchPoint = floatArrayOf(event.x, event.y) // 将View坐标系的触摸点转换为Bitmap坐标系的点 matrix.mapPoints(touchPoint) val correctedX = touchPoint[0].toInt() val correctedY = touchPoint[1].toInt() // 过滤超出Bitmap范围的触摸点 if (correctedX < 0 || correctedX >= bitmap.width || correctedY < 0 || correctedY >= bitmap.height) { return false } when (event.action) { MotionEvent.ACTION_MOVE -> { drawOnImage(correctedX, correctedY) return true } MotionEvent.ACTION_DOWN -> { performClick() return true } MotionEvent.ACTION_UP -> { drawOnImage(correctedX, correctedY) drawingListener?.onDrawing() return true } } return false }
2. 修正绘图函数
确保操作的Bitmap是可变的(避免原Bitmap不可修改导致绘图无效):
fun drawOnImage(x: Int, y: Int) { val bitmapDrawable = drawable as? BitmapDrawable ?: return // 拷贝不可变Bitmap为可修改版本 val targetBitmap = if (bitmapDrawable.bitmap.isMutable) { bitmapDrawable.bitmap } else { bitmapDrawable.bitmap.copy(Bitmap.Config.ARGB_8888, true) } val canvas = Canvas(targetBitmap) canvas.drawCircle(x.toFloat(), y.toFloat(), paint.strokeWidth / 2, paint) // 更新ImageView的Drawable setImageBitmap(targetBitmap) invalidate() }
3. 明确ImageView的缩放模式
在XML布局中显式设置scaleType(确保与预期显示逻辑一致):
<com.my.app.CustomImageView android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:scaleType="fitCenter" android:contentDescription="paint" />
原理说明
ImageView的imageMatrix已经封装了所有适配屏幕、缩放图片的变换逻辑,使用mapPoints()可以直接将View上的触摸坐标转换为图片内部的坐标,避免手动计算的误差。同时,部分Bitmap资源默认是不可变的,必须拷贝为可变Bitmap才能在上面绘图。
内容的提问来源于stack exchange,提问作者RGS
相关产品推荐
相关产品推荐

