Being Android programming newbie I am trying to find out, if the user has touched a child (the yellow tile at the left in the picture below) at a custom View (source code: MyView.java):
For hitTesting I have written the following method:
private Drawable hitTest(int x, int y) {
for (Drawable tile: mTiles) {
Rect rect = tile.getBounds();
if (rect.contains(x, y))
return tile;
}
return null;
}
However I don't know, how to translate the MotionEvent coordinates, before passing them to the above method. I have tried many possible combinations, involving the mScale
and mOffset
properties of my custom View
(I do not want to use View.scrollTo()
and View.setScaleX()
methods - but handle the offset and scale myself).
When I start randomly touching the screen, then I sometimes hit the tiles - so I see that my hitTest method is okay, but I just need to figure out the proper translation.
Do I miss something here, should I maybe add some translation between dp
and real pixels?
public boolean onTouchEvent(MotionEvent e) {
Log.d("onToucheEvent", "mScale=" + mScale +
", mOffsetX=" + mOffsetX +
", mOffsetY=" + mOffsetY +
", e.getX()=" + e.getX() +
", e.getY()=" + e.getY() +
", e.getRawX()=" + e.getRawX() +
", e.getRawY()=" + e.getRawY()
);
int x = (int) (e.getX() / mScale - mOffsetX);
int y = (int) (e.getY() / mScale- mOffsetY);
Drawable tile = hitTest(x, y);
Log.d("onToucheEvent", "tile=" + tile);
boolean retVal = mScaleDetector.onTouchEvent(e);
retVal = mGestureDetector.onTouchEvent(e) || retVal;
return retVal || super.onTouchEvent(e);
}
UPDATE: Following pskink's advice (thanks) I am trying to use Matrix
and have change my custom MyView.java to:
protected void onDraw(Canvas canvas) {
mMatrix.reset();
mMatrix.setTranslate(mOffsetX, mOffsetY);
mMatrix.postScale(mScale, mScale);
canvas.setMatrix(mMatrix);
mGameBoard.draw(canvas);
for (Drawable tile: mTiles) {
tile.draw(canvas);
}
}
public boolean onTouchEvent(MotionEvent e) {
float[] point = new float[] {e.getX(), e.getY()};
Matrix inverse = new Matrix();
mMatrix.invert(inverse);
inverse.mapPoints(point);
float density = getResources().getDisplayMetrics().density;
point[0] /= density;
point[1] /= density;
Drawable tile = hitTest((int) point[0], (int) point[1]);
Log.d("onToucheEvent", "tile=" + tile);
}
But unfortunately my hitTest()
does not find any touched tiles.