Search code examples
androidevent-handlingtouch

Determine Touch Input Consumer


I have a view roughly defined as

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

and a TouchListener / Behavior as

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

which attaches to MyView1 (verified with logging). This logic works well on another view MyView2 (which also extends LinearLayout) but not for MyView1 for reasons I've yet to determine. In MyView1 touch-events (tapping anywhere within the layout) are detected in onInterceptTouchEvent but not in onTouchEvent. TouchBehavior.onTouchEvent() is never invoked when TouchBehavior is attached to MyView1 regardless of whether either or both of onInterceptTouchEvent and onTouchEvent are defined on MyView1.

From Android docs' Managing Touch Events in a ViewGroup it is my understanding that onInterceptTouchEvent() is called when a touch event is detected in a ViewGroup and it can return true to indicate that it will intercept/consume the event and not propagate to its children. In my example, MyView1.onInterceptTouchEvent is returning false using its super-class logic which means it is available for consumption by itself or children. However, since MyView1.onTouchEvent is not invoked I think the event is consumed by a child sub-view.

Having said all of that, maybe the problem is obvious to someone else but it leads me to think that the event is consumed by a child sub-view or one of its listeners and so have searched for a way to determine the final consumer of that MotionEvent. MyView1 and MyView2 each have 8-10 subviews (layout/widget/etc) and are very different structurally.

So how can I determine which View has consumed some input event (MotionEvent)?


Solution

  • You can do as follow. Set a breaking point at ViewGroup.dispatchTouchEvent method. If you are using SDK 25 then you can use line 2266. The child View there is the one who consume the touch event.

    You can also configure the break point there so that the IDE will log to the console.