如何在Android中正确地将像素坐标转换为画布坐标?

时间:2011-07-28 00:23:50

标签: android events pixel android-canvas

我使用MotionEvent在Android SurfaceView中长按一次GestureListener。然后我需要将MotionEvent的坐标转换为画布坐标,我可以从中生成自定义地图坐标(而不是Google地图)。

根据我的阅读,我认为给定MotionEvent ee.getX()e.getY()得到像素坐标。如何将这些坐标转换为SurfaceView的画布坐标?

我的GestureListener用于收听长时间点击:

/**
* Overrides touch gestures not handled by the default touch listener
*/
private class GestureListener extends GestureDetector.SimpleOnGestureListener {

  @Override
  public void onLongPress(MotionEvent e) {
     Point p = new Point();
     p.x =  (int) e.getX();
     p.y = (int) e.getY();
     //TODO translate p to canvas coordinates
  }
}

提前致谢!

修改 这与屏幕尺寸/分辨率/深度和画布'Rect对象有关吗?

6 个答案:

答案 0 :(得分:8)

您可以尝试使用MotionEvent.getRawX()/getRawY()方法而不是getX()/getY()

// get the surfaceView's location on screen
int[] loc = new int[2];
surfaceView.getLocationOnScreen(loc);
// calculate delta
int left = e.getRawX()-loc[0];
int top = e.getRawY()-loc[1];

答案 1 :(得分:5)

嗯,你有x,y显示的屏幕px,你可以通过以下方式调用canvas px:

Canvas c = new Canvas();
int cx = c.getWidth();
int cy = c.getHeight();
...
Display display = getWindowManager().getDefaultDisplay(); 
int sx = display.getWidth();
int sy = display.getHeight();

然后,您可以在视图和屏幕中使用给定的px来映射屏幕触摸视图。

canvasCoordX = p.x*((float)cx/(float)sx);
canvasCoordY = p.y*((float)cy/(float)sy);

有关屏幕管理器的详细信息,请参阅http://developer.android.com/reference/android/view/WindowManager.html。我认为需要在活动中初始化才能发挥作用。

答案 2 :(得分:4)

我最近在做一些非常相似的事情时遇到了这个问题,经过一些试验和错误以及大量的谷歌搜索我最终调整了这个答案(https://stackoverflow.com/a/9945896/1131180):

(e是一个MotionEvent,因此使用此代码的最佳位置是onTouch或onLongPress)

mClickCoords = new float[2];

//e is the motionevent that contains the screen touch we
//want to translate into a canvas coordinate
mClickCoords[0] = e.getX();
mClickCoords[1] = e.getY();

Matrix matrix = new Matrix();
matrix.set(getMatrix());

//this is where you apply any translations/scaling/rotation etc.
//Typically you want to apply the same adjustments that you apply
//in your onDraw().

matrix.preTranslate(mVirtualX, mVirtualY);
matrix.preScale(mScaleFactor, mScaleFactor, mPivotX, mPivotY);

// invert the matrix, creating the mapping from screen 
//coordinates to canvas coordinates
matrix.invert(matrix); 

//apply the mapping
matrix.mapPoints(mClickCoords);

//mClickCoords[0] is the canvas x coordinate and
//mClickCoords[1] is the y coordinate.

可以在这里应用一些明显的优化,但我认为这种方式更为清晰。

答案 3 :(得分:1)

如果我理解正确,你会在surfaceview里面看一个画布。如果是这样 尝试返回左边的VIEW.getLeft() | getTop()视图相对于其父级的顶部位置。

float x= e.getX() - canvasView.getLeft();
float y= e.getY() - canvasView.getTop();

答案 4 :(得分:0)

如果您使用滚动,那么画布上的实际y是

float y = event.getY() + arg0.getScrollY();

答案 5 :(得分:0)

我在这些情况下所做的只是:

  1. 通过点击
  2. 将监听器放在您想要获得坐标的View / ViewGroup上
  3. 让它在本地存储
  4. 任何想要访问它们的人都应该通过帮助方法请求它们。
  5. 翻译完成......