0

我正在执行一个非常小的测试来调试更大的东西,并且无法弄清楚是什么导致了这个问题。

我有一个 ImageView、一个 Canvas 和一个位图。我初始化 ImageView 并将其设置为位图,然后将 Canvas 设置为位图,如下所示:

_image.setImageBitmap(bitmap);
Canvas canvas = new Canvas(bitmap);

然后,我将 onTouchListener 附加到 _image 并侦听要检测的 MotionEvent.ACTION_UP。那时我在画布上画了一个矩形,如下所示:

Rect rect = new Rect((int)event.getX(),event.getY(),event.getX()+20,event.getY()+20);
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(rect,paint);

我已经尝试过使用不同大小的位图图像,小到小于完整显示,到非常接近精确大小,大到更大,我永远无法让 Rect 在我的手指触摸屏幕的地方正确绘制。我在 getX() 上尝试了不同的转换,尝试从 dp 转换为 dp,改用 getRawX/Y();基本上是一堆不同的解决方案,但都没有奏效。我尝试获取位图大小与屏幕大小的比率并乘以/除以;没有什么能够解决这个非常简单的问题。

很可能我在某个时候尝试了正确的方法,只是错误地实施了它。我真的很感激一些关于是什么导致 Rect 在它所在的位置绘制的建议,需要什么转换才能让它在触摸发生的地方绘制,以及为什么。'为什么'是因为我想从中学习。

编辑:这是所发生情况的近似值。红色矩形是实际触摸发生的地方,蓝色是它被绘制的地方。它从你得到的 X=Y=0 扩展得越远。另外,我刚刚注意到它还会根据您使用的图像的宽度和高度进行缩放。

例子

4

2 回答 2

2

所以,我相信我已经弄清楚了允许我将 onTouch 坐标转换到 Canvas 上的数学。

我真的想走这条路(而不是 ImageView 的自定义子类)的原因是因为我对矩形的绘制并不是感兴趣:我更感兴趣的是准确地将 onTouch 坐标映射到特定的 OCRed 文本字符串在位图中。我进行这个练习的原因是为了弄清楚为什么没有将触摸归因于正确的文本行,并且我使用绘制的 Rects 来估计触摸被记录的位置。

所以,关于数学,结果比我担心的要简单得多:

int x1 = (int)(event.getX() * ((float) canvas.getWidth() / _image.getRight()));
int y1 = (int)(event.getY() * ((float) canvas.getHeight() / _image.getBottom()));

我将 onTouch 坐标乘以 Canvas 尺寸与 ImageView 尺寸之比,然后将其转换为浮点数。绘制如下:

rect = new Rect(x1-10,y1-10,x1+10,y1+10);
    //I took the advice about centering the Rect around the touch for clarity
paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(rect,paint);

无论位图大小如何,矩形都恰好是触摸的位置。

我发现它没有引起我打电话的任何问题很有趣

_image.setAdjustViewBounds(true);

在我的程序的早期,我这样做是为了从位图中删除一些填充(由于某种原因而出现,可能是由于缩放)。同样有趣的是 ImageView 包含在 ScrollLayout 中,但是即使图像足够大可以滚动,它似乎也不需要考虑滚动位移。

感谢 kcoppock 花时间帮助我,也感谢其他用户(当他意识到他误解了我时,他的评论被删除了)也花时间。

于 2014-06-11T05:21:59.057 回答
1

我想您的实际位图比视图大并且按比例缩小。由于您正在绘制位图的坐标,并且该位图正在按比例缩小,因此该位置也将按比例缩小以匹配。

您更可能想要做的是创建 ImageView 的子类,然后根据 onTouchEvent() 中接收到的位置在 onDraw() 中绘制 Rect。或者,您可以做一些数学运算来确定位图相对于视图大小被缩小了多少,并通过逆向放大坐标。这个可触摸的 ImageView 的快速实现是这样的:

public class DrawableImageView extends ImageView {
    private final int mRectSize;
    private final Paint mPaint;
    private final Rect mRect = new Rect();

    public DrawableImageView(Context context) {
        super(context);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mRectSize = (int) (getResources().getDisplayMetrics().density * 20);
    }

    // Other constructors omitted for brevity

    @Override public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            final int x = (int) event.getX();
            final int y = (int) event.getY();

            mRect.set(x, y, x + mRectSize, y + mRectSize);
            mRect.offset(-(mRectSize / 2), -(mRectSize / 2));

            invalidate();
            return true;
        } else {
            return super.onTouchEvent(event);
        }
    }

    @Override protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawRect(mRect, mPaint);
    }
}
于 2014-06-10T20:25:56.277 回答