Android运动事件:找出运动是否发生在视图之外

yzuktlbb  于 2023-02-06  发布在  Android
关注(0)|答案(7)|浏览(172)

我有一个按钮和OnTouchListener连接到它。我如何找到如果议案(当用户按下按钮时)发生在内部还是外部?两个事件。getAction()和事件.getActionMasked()只返回0、1或2,分别为ActionDown、ActionUp、ActionMove,有一个常量MotionEvent.ACTION_OUTSIDE,为4,但不知何故,即使我将touch拖到按钮之外,我也没有收到它-我仍然从两种方法收到2。

**UPD:**我找到了一个很好的解决方案--在ACTION_UP之后检查视图的聚焦状态。如果它没有聚焦,这意味着移动发生在视图之外。

tyky79it

tyky79it1#

MotionEvent.ACTION_OUTSIDE不适用于视图的。
一种解决方案是获取X和Y触摸位置,并验证其是否在视图的边界内。

@Override
public boolean onTouchEvent(MotionEvent e) {
    if (isInside(myView, e))
        Log.i(TAG, "TOUCH INSIDE");
    else
        Log.i(TAG, "TOUCH OUTSIDE");
    return true;
}

private boolean isInside(View v, MotionEvent e) {
    return !(e.getX() < 0 || e.getY() < 0
            || e.getX() > v.getMeasuredWidth()
            || e.getY() > v.getMeasuredHeight());
}
ar7v8xwq

ar7v8xwq2#

该标志仅适用于Windows,不适用于视图。当您将手指从视图上移开时,您将得到ACTION_MOVE,事件仍保留在其起源的视图中。如果需要澄清,请查看SeekBar的源代码:即使你把手指从吧台上移开,拇指还是会拖!
要在窗口级别执行此操作,请使用FLAG_WATCH_OUTSIDE_TOUCH,它工作得很好。

ibrsph3r

ibrsph3r3#

case MotionEvent.ACTION_CANCEL对我很有效。

xriantvc

xriantvc4#

如果OnTouchListener位于Button上,则只能从Button内接收运动事件。只有当运动事件首次超出View的边界时,才会调用MotionEvent.ACTION_OUTSIDE,并且应将其视为ACTION_UP

juud5qan

juud5qan5#

public static boolean touchWithinBounds(MotionEvent event, View view) {
    if (event == null || view == null || view.getWidth() == 0 || view.getHeight() == 0)
        return false;

    int[] viewLocation = new int[2];
    view.getLocationOnScreen(viewLocation);
    int viewMaxX = viewLocation[0] + view.getWidth() - 1;
    int viewMaxY = viewLocation[1] + view.getHeight() - 1;
    return (event.getRawX() <= viewMaxX && event.getRawX() >= viewLocation[0]
        && event.getRawY() <= viewMaxY && event.getRawY() >= viewLocation[1]);
}

从不同视图转发触摸事件时的解决方案

z9zf31ra

z9zf31ra6#

试试这个

private View.OnTouchListener handleTouch = new View.OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {

    int x = (int) event.getX();
    int y = (int) event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i("TAG", "touched down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.i("TAG", "moving: (" + x + ", " + y + ")");
            break;
        case MotionEvent.ACTION_UP:
            Log.i("TAG", "touched up");
            // do what you want when touch active
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.if("TAG","touched canceled")
            // outside of the view 
            //ACTION_MOVE present 
            break:

    }

    return true;
}

};

ui7jx7zq

ui7jx7zq7#

下面是一个Kotlin扩展函数,您可以从触摸监听器中使用它来检查所提供的事件是否在给定的视图中:

private fun MotionEvent.isInside(v: View): Boolean {
    return Rect().apply(v::getGlobalVisibleRect).contains(rawX.toInt(), rawY.toInt())
}

相关问题