根据 GreyBeardedGeek 关于 .getLocationOnScreen 的提示,这里有一个示例 onTouchListener,它可以用手指移动 View。它成功地容纳了菜单、工具栏、状态栏、不在任一轴上的父视图等。我想我会分享这个,因为我已经看到了很多关于该主题的帖子,但没有一个真正完全回答了这个问题。它是故意罗嗦的,并且使用了比必要更多的当地人来帮助说明正在发生的事情。
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 返回相对于父 View 的坐标。这就是处理非全屏父视图的方式。这两个坐标对之间的区别在于将 MotionEvent.getRawX/Y 的绝对坐标转换为 View.setX/Y 所需的父视图相对坐标的偏移量。
非常感谢 GreyBeardedGeek 识别 View.getLocationOnScreen。希望这段代码摘录对其他人有所帮助。谢谢!