onTouch:检测ACTION_UP而不阻止其他触摸事件

时间:2018-09-13 00:23:01

标签: android android-gesture android-touch-event

我有一个充当按钮的自定义视图。我自己在画所有画布。现在,我在ACTION_DOWN时绘制轮廓,并在ACTION_UPACTION_CANCEL之后将其删除。

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.e("test", "ACTION_DOWN");
            break;
        case MotionEvent.ACTION_UP:
            Log.e("test", "ACTION_UP");
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.e("test", "ACTION_CANCEL");
            break;
    }

    return true;
}

这可以为我工作,除了现在它正在阻止该视图后面的另一个手势检测到ACTION_MOVE(向左滚动)。

如果我返回false,则可以正常工作,但是现在不调用ACTION_UP

如果手指松开,我想打电话给ACTION_UP,否则将事件传递给其他人。

1 个答案:

答案 0 :(得分:0)

您是否尝试覆盖dispatchTouchEvent

https://developer.android.com/reference/android/view/View.html#dispatchTouchEvent(android.view.MotionEvent)

更新:

所以触摸事件有点像野兽。它的缺点是这个...

  1. 它们首先从您的“活动”中的根容器冒泡。这是通过调用dispatchTouchEvent然后调用onInterceptTouchEvent来完成的,假设拦截没有被子视图阻止。
  2. 如果没有视图拦截该事件,它将冒泡到调用onTouch的叶节点(例如按钮)。如果节点不处理该节点(返回true),则其父节点会获得机会,依此类推。

这意味着您可以使用dispatchTouchEventonInterceptTouchEvent来监视触摸事件而无需更改行为。除非您实际上要拦截事件,否则我建议使用dispatchTouchEvent,因为它可以保证运行,而拦截可能会被阻止(例如:DrawerLayout会拦截边缘附近的触摸事件以打开抽屉)

所以最终结果是:

public class MyView extends Button {
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                Log.e("test", "ACTION_DOWN");
                break;
            case MotionEvent.ACTION_UP:
                Log.e("test", "ACTION_UP");
                break;
            case MotionEvent.ACTION_CANCEL:
                Log.e("test", "ACTION_CANCEL");
                break;
        }
        return super.dispatchTouchEvent(event);
    }
}

更新:

对不起,由于某种原因(主要是我的阅读能力很差),我一直在与我们打交道。这就是我要做的...

继续执行onTouch,然后返回true以使用所有事件。这意味着从您的视图开始的所有触摸事件都会被吃掉。然后,我们要做的就是将点转换为父级的坐标空间,并手动向上传递touch事件,它将在您的自定义视图中看起来像这样……

private boolean passingTouchEventToParent = true;
final private Rect hitRect = Rect();
@Override
public boolean onTouch(MotionEvent event) {
    // Handle your custom logic here

    final ViewParent viewParent = getParent();
    if (passingTouchEventToParent &&
            viewParent != null &&
            viewParent instanceof View) {
        // Gets this view's hit rectangle in the parent's space
        getHitRect(hitRect);
        event.offsetLocation((float) hitRect.left, (float) hitRect.top);
        passingTouchEventToParent = viewParent.onTouchEvent(event);
    }
    if (event.getActionMasked() == MotionEvent.ACTION_UP) {
        // Motion event finished, reset passingTouchEventToParent
        passingTouchEventToParent = true;
    }
    return true;
}