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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:26:13