Android:由菜单/工具栏补偿屏幕偏移?

时间:2013-05-22 03:38:24

标签: android graphics view coordinates move

MotionEvent.getRawX / .getRawY返回绝对坐标(即基于整个屏幕)。但接收MotionEvent的View可能(可能是)另一个View的子节点,它本身可能在屏幕上有一些偏移等等。

特别是,我正在尝试使用基本应用程序,并且屏幕顶部会显示Android菜单/工具栏(带有时钟等)。当我调用.getRawX / .getRawY时,我会得到整个显示器的准确X / Y坐标 - 但是如果可以有菜单,或者如果(宏)我如何确定它们与屏幕上View的位置有何关系?父视图本身小于屏幕并偏离其边缘?

现在,如果我使用.getRawX / .getRawY的返回值来重新定位视图,它们可以正常工作,但视图会“跳”到屏幕顶部菜单的高度,因为“绝对“Y值基本上由父视图的垂直偏移量增加,因为它上面的菜单。因此,需要一种通用的案例方法来确定父视图在屏幕的绝对坐标中的位置,以便在用于重新定位相关视图之前可以调整原始X / Y值。

我不打算发布代码,因为它基本上是在这个和许多其他网站上的“通过触摸移动视图”的每个其他示例的重复。我没有找到我想要找到的错误...我正在寻找将MotionEvent的绝对坐标与任何未运行100%全屏的应用程序的相对坐标相关联的方法。

2 个答案:

答案 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。希望此代码摘录将帮助其他人。谢谢!