11

我有一个按钮和 OnTouchListener 附加到它。我怎样才能找到运动(当用户按下按钮时)发生在它内部还是外部?event.getAction() 和 event.getActionMasked() 都只返回 0、1 或 2,分别是 ActionDown、ActionUp、ActionMove。有一个常量 MotionEvent.ACTION_OUTSIDE,即 4,但不知何故,即使我将触摸拖到按钮外,我也没有收到它 - 我仍然从两种方法中收到 2。有什么问题?

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

4

6 回答 6

13

MotionEvent.ACTION_OUTSIDE 不适用于 View。

一种解决方案是获取 X 和 Y 触摸位置并验证它是否在视图的边界内。可以这样做:

@Override
public boolean onTouchEvent(MotionEvent e) {
    if (isInside())
        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());
}
于 2016-09-10T17:21:21.033 回答
9

该标志仅适用于 Windows,不适用于视图。ACTION_MOVE当您将手指从视图上移开时,您会得到,事件将保留在它起源的视图中。如果您需要澄清,请查看源代码SeekBar:即使您将手指从栏上移开,拇指仍然会拖动!

对于在窗口级别使用执行此操作FLAG_WATCH_OUTSIDE_TOUCH,它工作得很好。

于 2012-06-23T19:15:07.807 回答
8

case MotionEvent.ACTION_CANCEL为我工作。

于 2013-04-10T12:38:09.693 回答
4

如果 位于OnTouchListenerButton,您将仅接收来自 中的运动事件ButtonMotionEvent.ACTION_OUTSIDE只会在运动事件第一次超出 的范围时调用,View您应该像对待它一样对待它ACTION_UP

于 2012-06-23T19:16:12.557 回答
1
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]);
}

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

于 2017-11-03T12:06:26.053 回答
0

试试这个

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;
}

};

于 2022-01-30T17:20:55.927 回答