2

I respond to touch events inside a custom View in onTouchEvent(MotionEvent event). I'm having trouble with an inconsistency in coordinates: event.getRaw(Y) returns the Y coordinate of a touch including the status bar, but myView.getTop() returns the Y coordinate of the top of the view excluding the status bar. I've resorted to the following hack to correct for the height of the status bar:

// Get the size of the visible window (which excludes the status bar)
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);

// Get the coordinates of the touch event, subtracting the top margin
final int x = (int) event.getRawX();
final int y = (int) event.getRawY() - rect.top;

Is there a better solution?

1''
  • 26,823
  • 32
  • 143
  • 200
  • What form do you want the final X/Y values to take? Including the status bar, exluding them, or relative to the parent view that recieved the touch event? – Alexander Lucas Dec 27 '12 at 19:52
  • Excluding the status bar. For instance, my custom View starts at y=0, so I'd like the very top of that view to be y=0 instead of y=38 or something. – 1'' Dec 27 '12 at 20:04
  • In this particular case, why don't getX and getY work for you, since they're relative to the top left of the view? – Alexander Lucas Dec 27 '12 at 20:38

1 Answers1

4

If you only care about the coordinate relative to your parent view (for instance, you want to always assume the top left of your view is 0,0), you can just use getX() and getY() instead of their raw equivalents.

Otherwise, Basically you're trying to take X/Y relative to the screen (getRawX, getRawY) and convert them to X/Y coordinates relative to the Window (status bar is not part of the window).

Your current solution will work, but as discussed elsewhere, getWindowVisibileDisplayFrame has been slightly broken in the past. A safer method might be to determine the view's location in the window, and then use the x/y coordinates relative to that view.

int[] coords = new int[2];
myView.getLocationInWindow(coords);

final int x = event.getRawX() - coords[0];
final int y = event.getRawY() - coords[1];
Community
  • 1
  • 1
Alexander Lucas
  • 22,171
  • 3
  • 46
  • 43
  • This works great! I should clarify that I'm accessing this from the activity of which myView is a child, so getX() and getRawX() give the same result (I'm guessing because the activity fills the screen)? If myView has a margin around it, my code doesn't correct for that, but yours does. – 1'' Dec 27 '12 at 22:35
  • Modified as I typed in the arithmetic wrong. It's getX plus getLocationInWindow, not getRawX + getLocationInWindow :) – Alexander Lucas Dec 27 '12 at 22:54
  • You definitely have to subtract coords rather than adding them. For instance, if event.getX() is 70 and the x-coordinate of the left side of myView is coords[0] = 50, then you want x = 20. And it doesn't seem to matter in this case whether getX() or getRawX() is used, so I'm just using getRawX() to remind myself that these are raw values. – 1'' Dec 27 '12 at 23:03
  • Ah, okay. I slightly misunderstood which coordinates you were looking for :) I Changed them back. – Alexander Lucas Dec 27 '12 at 23:10