确定触摸输入消费者

Determine Touch Input Consumer

我有一个观点大致定义为

class MyView1 extends LinearLayout {
        // for debugging, not actually needed
        @Override public boolean onTouchEvent(MotionEvent event) {
            Log.d(getClass().getSimpleName(), "");
        }

        // also for debugging, not actually needed
        @Override public boolean onInterceptTouchEvent(MotionEvent ev){
            boolean handle = super.onInterceptTouchEvent(ev);
            Log.v(getClass().getSimpleName(), "handle?=" + handle);
            return handle;
        }
    }
}

和 TouchListener/Behavior 为

class TouchBehavior implements View.OnTouchListener {
    View myView; // assigned in ctor
    public void attach() { myView.setOnTouchListener( this ); }
    @Override public boolean onTouch(View v, MotionEvent event) {
        Log.d(getClass().getSimpleName(), "log just for detection");
        // actual logic...
    }

附加到 MyView1(通过日志记录验证)。此逻辑适用于另一个视图 MyView2(也扩展了 LinearLayout)但不适用于 MyView1,原因我尚未确定。在 MyView1 中,touch-events(点击布局中的任意位置)在 onInterceptTouchEvent 中检测到,但在 onTouchEvent 中检测不到。当 TouchBehavior 附加到 MyView1 时,永远不会调用 TouchBehavior.onTouchEvent(),无论 onInterceptTouchEventonTouchEvent 中的一个或两个是否在 MyView1 上定义。

来自 Android 文档的 Managing Touch Events in a ViewGroup 我的理解是 onInterceptTouchEvent()ViewGroup 中检测到触摸事件时被调用并且它可以 return true 表示它将 intercept/consume 事件而不传播到其 children。在我的示例中,MyView1.onInterceptTouchEvent 使用其 super-class 逻辑是 returning false,这意味着它可以单独使用或 children。但是,由于未调用 MyView1.onTouchEvent 我认为该事件由 child sub-view.

消耗

说了这么多,也许这个问题对其他人来说是显而易见的,但它让我认为事件被 child sub-view 或其听众之一消耗了,所以搜索了一种方法来确定 MotionEvent 的最终消费者。 MyView1MyView2 各有 8-10 个子视图 (layout/widget/etc),并且在结构上有很大不同。

那么我如何确定哪个 View 消耗了一些输入事件 (MotionEvent)?

public class Myview extends LinearLayout {
    public Myview(Context context) {
        super(context);
    }

    public Myview(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public Myview(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Toast.makeText(getContext(), "onTouchEvent", Toast.LENGTH_SHORT).show();
        return super.onTouchEvent(event);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Toast.makeText(getContext(), "onInterceptTouchEvent", Toast.LENGTH_SHORT).show();
        boolean handle = super.onInterceptTouchEvent(ev);
        return handle;
    }


}

在上面的 TouchBehavior class OnTouch 方法中你应该 return false.
如果你 return true 只有 onInterceptTouchEvent 方法会触发。如果你 return false onInterceptTouchEventonTouchEvent 都会触发

您可以按照以下步骤操作。在 ViewGroup.dispatchTouchEvent 方法处设置断点。如果您使用的是 SDK 25,那么您可以使用第 2266 行。child View 那里是消费触摸事件的人。

您还可以在那里配置断点,以便 IDE 将登录到控制台。