MotionEvent.getRawX / .getRawY返回绝对坐标(即基于整个屏幕)。但接收MotionEvent的View可能(可能是)另一个View的子节点,它本身可能在屏幕上有一些偏移等等。
特别是,我正在尝试使用基本应用程序,并且屏幕顶部会显示Android菜单/工具栏(带有时钟等)。当我调用.getRawX / .getRawY时,我会得到整个显示器的准确X / Y坐标 - 但是如果可以有菜单,或者如果(宏)我如何确定它们与屏幕上View的位置有何关系?父视图本身小于屏幕并偏离其边缘?
现在,如果我使用.getRawX / .getRawY的返回值来重新定位视图,它们可以正常工作,但视图会“跳”到屏幕顶部菜单的高度,因为“绝对“Y值基本上由父视图的垂直偏移量增加,因为它上面的菜单。因此,需要一种通用的案例方法来确定父视图在屏幕的绝对坐标中的位置,以便在用于重新定位相关视图之前可以调整原始X / Y值。
我不打算发布代码,因为它基本上是在这个和许多其他网站上的“通过触摸移动视图”的每个其他示例的重复。我没有找到我想要找到的错误...我正在寻找将MotionEvent的绝对坐标与任何未运行100%全屏的应用程序的相对坐标相关联的方法。
答案 0 :(得分:2)
您可以使用View.getLocationOnScreen()查找视图的绝对屏幕坐标,然后在屏幕坐标中处理所有内容和/或基于此进行转换。
答案 1 :(得分:0)
基于GreyBeardedGeek关于.getLocationOnScreen的提示,下面是一个用手指移动视图的onTouchListener示例。它成功地容纳了菜单,工具栏,状态栏,父视图不在任何一个轴上等等。我以为我会分享这个,因为我看过很多关于这个主题的帖子,但没有一个真正完全回答了这个问题。它故意冗长,并且使用了比必要更多的本地人来帮助说明正在发生的事情。
public boolean onTouch(View v,MotionEvent event) {
boolean bExitValue = true;
int iOffsetX;
int iOffsetY;
int iNewX;
int iNewY;
int[] aLocation = new int [ 2 ];
int iAction;
iAction = event.getActionMasked();
if (MotionEvent.ACTION_MOVE == iAction) {
v.getLocationOnScreen(aLocation); // get absolute physical location of this View
iOffsetX = (aLocation [ 0 ] - (int) v.getX()); // subtract out this View's relative location within its parent View...
iOffsetY = (aLocation [ 1 ] - (int) v.getY()); // ...yielding the offsets that convert getRawX/Y's coords to setX/Y's coords
iNewX = (int) event.getRawX(); // get absolute physical coords of this touch
iNewY = (int) event.getRawY();
iNewX -= iOffsetX; // remove parent View's screen offset (calc'd above)
iNewY -= iOffsetY;
iNewX -= iRelX; // remove stored touch offset
iNewY -= iRelY;
v.setX(iNewX); // finally, move View to new coords (relative to its parent View)
v.setY(iNewY);
}
else if (MotionEvent.ACTION_DOWN == iAction) {
iRelX = (int) event.getX(); // preserve offset of this touch within the View
iRelY = (int) event.getY();
}
else {
bExitValue = false;
}
return(bExitValue);
}
关键点:
必须捕获视图中的触摸偏移并将其存储在ACTION_DOWN处理程序中,以保存到类级字段(即静态变量)。你想保留这个偏移量,以便View保持与手指的位置关系,但你不能只用每个ACTION_MOVE抓取一个新的副本,因为它们会完全抵消手指移动而不会发生任何移动。
View.getLocationOnScreen返回绝对坐标,而View.getX / Y返回相对于父视图的坐标。这是处理非全屏父视图的方式。这两个坐标对之间的差异是将MotionEvent.getRawX / Y的绝对坐标转换为View.setX / Y所需的父视图相对坐标的偏移量。
非常感谢GreyBeardedGeek识别View.getLocationOnScreen。希望此代码摘录将帮助其他人。谢谢!