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

发布于 2024-11-26 11:30:27 字数 817 浏览 1 评论 0原文

我正在使用 GestureListener 在 Android SurfaceView 中捕获长按的 MotionEvent。然后,我需要将 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 对象有关吗?

I am capturing a MotionEvent for a long click in an Android SurfaceView using a GestureListener. I then need to translate the coordinates of the MotionEvent to canvas coordinates, from which I can generate custom map coordinates (not Google Maps).

From what I have read, I take that given MotionEvent e, e.getX() and e.getY() get pixel coordinates. How can I convert these coordinates to the SurfaceView's canvas coordinates?

Here is my GestureListener for listening for long clicks:

/**
* 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
  }
}

Thanks in advance!

Edit:
Does this have to do with screen size/resolution/depth and the canvas' Rect object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

深海蓝天 2024-12-03 11:30:27

您可以尝试使用 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];

You might try using the MotionEvent.getRawX()/getRawY() methods instead of the 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];
悲喜皆因你 2024-12-03 11:30:27

好吧,您在 x,y 中获得了显示屏上的屏幕 px,并且您可以通过以下方式调用画布 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有关屏幕管理器的更多信息。我认为它需要在活动内部初始化才能工作。

Well, you have the screen px from the display in x,y, and you can call the canvas px via:

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

Then, you can do the math to map the screen touch view , with the given px in both the view and the screen.

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

See http://developer.android.com/reference/android/view/WindowManager.html for more info on the screen manager. I think it needs to be initialized inside an activity to work.

忆梦 2024-12-03 11:30:27

我最近在做一些非常类似的事情时遇到了这个问题,经过一些尝试和错误以及大量的谷歌搜索,我最终适应了这个答案(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.

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

I recently came upon this problem while doing something very similiar and after some trial and error and lots of googling I ended up adapting this answer (https://stackoverflow.com/a/9945896/1131180) :

(e is a MotionEvent, so the best place to use this code would be in onTouch or 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.

There are some obvious optimizations that can be applied here but I think it is more clear this way.

抽个烟儿 2024-12-03 11:30:27

如果我理解正确的话,你在表面视图中有一个画布视图。如果是这样
尝试 VIEW.getLeft() | getTop() 返回左侧 |视图相对于其父视图的顶部位置。

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

If i understand correctly you have a canvas View inside surfaceview. If so
try VIEW.getLeft() | getTop() that returns the left | top position of the view relative to it's parent.

float x= e.getX() - canvasView.getLeft();
float y= e.getY() - canvasView.getTop();
拒绝两难 2024-12-03 11:30:27

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

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

if you are using scrolling, then the actual y on the canvas is

float y = event.getY() + arg0.getScrollY();
迷路的信 2024-12-03 11:30:27

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

  1. 在您想要通过单击获取其坐标的任何 View/ViewGroup 上放置一个侦听器
  2. 使其将它们存储在本地
  3. 任何想要访问它们的人都应该通过辅助方法请求它们。

并且翻译完成了...

What I do in these situations is just:

  1. put a listener on whatever View/ViewGroup whose coordinates you wanna get by click
  2. Make it store them locally
  3. Whoever wants to access them should just request them via helper method.

And translation is done...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文