【问题标题】:Android: Compensate for screen offset due to menus/toolbars?Android:补偿由于菜单/工具栏引起的屏幕偏移?
【发布时间】:2013-05-22 03:38:24
【问题描述】:

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

特别是,我现在正在试验一个基本应用程序,Android 菜单/工具栏(带有时钟等)在屏幕顶部可见。当我调用 .getRawX/.getRawY 时,我得到了整个显示器的准确 X/Y 坐标 - 但是如果可以有菜单,或者如果 (grand)父视图本身比屏幕小并偏离其边缘?

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

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

【问题讨论】:

    标签: android graphics view coordinates move


    【解决方案1】:

    您可以使用 View.getLocationOnScreen() 来查找视图的绝对屏幕坐标,然后在屏幕坐标中计算所有内容和/或您自己根据该坐标进行转换。

    【讨论】:

    • 太棒了,这正是我想要的。课程的深度如此之深,以至于有时很难在大海捞针中找到那根针。但是,请参阅我上面的编辑以获取更多 cmets。谢谢!
    【解决方案2】:

    根据 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 返回相对于父视图的坐标。这就是处理非全屏父视图的方式。这两个坐标对之间的区别在于将 MotionEvent.getRawX/Y 的绝对坐标转换为 View.setX/Y 所需的父视图相对坐标的偏移量。

    非常感谢 GreyBeardedGeek 识别 View.getLocationOnScreen。希望这段代码摘录对其他人有所帮助。谢谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-09
      • 1970-01-01
      • 2014-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-02
      • 1970-01-01
      相关资源
      最近更新 更多