在检测到onTouch的位置绘制一个小Rect

时间:2014-06-10 17:22:25

标签: android imageview ontouch

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

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

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

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

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进一步缩放。此外,我只是注意到它也会根据您正在使用的图像的宽度和高度进行缩放。

Example

2 个答案:

答案 0 :(得分:2)

所以,我相信我已经找到了允许我将onTouch坐标转换为Canvas的数学运算。

我之所以想要走这条路线(而不是ImageView的自定义子类)的原因是因为我并非真的对绘制矩形感兴趣:I&#39 ; m更感兴趣的是将onTouch坐标精确映射到位图中的特定OCR文本字符串。我进行这项练习的原因是为了弄清楚为什么触摸不归因于正确的文本行,我使用绘制的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);

无论位图大小如何,Rect都是触摸的确切位置。

我觉得有趣的是它没有引起任何我称之为

的问题
_image.setAdjustViewBounds(true);

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

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

答案 1 :(得分:1)

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

你更想要做的是创建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);
    }
}