【问题标题】:onTouch: detect ACTION_UP without blocking other touch eventsonTouch:在不阻塞其他触摸事件的情况下检测 ACTION_UP
【发布时间】:2019-02-17 16:15:53
【问题描述】:

我有一个用作按钮的自定义视图。我自己画所有的画布。现在我在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,否则将事件向下传递。

【问题讨论】:

  • 你可以使用GestureDetector
  • @DrumRobot 你是什么意思。注意我不能触摸其他视图。只有这个

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


【解决方案1】:

您是否尝试过覆盖dispatchTouchEvent

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

更新:

所以触摸事件有点像野兽。它的概要是这样的……

  1. 它们首先从 Activity 的根容器中冒出。这是通过调用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 以消耗所有事件。这意味着在您的视图上开始的任何触摸事件都将被吃掉。然后我们要做的是将点转换到父坐标空间并手动向上传递触摸事件,它会在您的自定义视图中看起来像这样......

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

【讨论】:

  • 你能举个例子吗?
  • 这种方式只检测到ACTION_DOWN。我已经阅读了一些关于它的文章并且尽可能了解,如果我没有在我的视图中捕捉到ACTION_DOWN,那么它之后将永远不会捕捉到任何其他视图。
  • 哦,好吧,我正在扩展 View,现在使用 Button 我可以获得所有操作,但这样 Button 总是会消耗所有操作。查看onInterceptTouchEvent 可能是我在父视图组中需要的。只是我需要想出一些逻辑来仅拦截 ACTION_MOVE 并在返回 true 之后,因此视图或视图组不会消耗更多操作
  • 今晚我会试着整理一些东西给你测试
  • 不是我想要的,但帮助我找到了正确的方向
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多