View.OnTouchListener() does not work on parent layout

Hong Wei Wang picture Hong Wei Wang · Jan 21, 2014 · Viewed 8.8k times · Source

I've set a View.OnTouchListener on a parent layout, but it doesn't appear to work.

Here is the XML for the UI:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="vertical"
    android:id="@+id/mainActivityLinearLayout"
    android:background="@drawable/listviewborder"
    tools:context=".MainActivity" >

    <View
        android:id="@+id/lineView"
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@color/gray" />

    <ListView
        android:id="@+id/gameListView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:dividerHeight="2dp" />

</LinearLayout>

Here is the OnTouchListener set on the parent layout:

mainActivityView = this.findViewById(R.id.mainActivityLinearLayout);
mainActivityView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            System.out.println("Touch test activity");
            return true;
        }
    });

onTouch() is never called and the string never prints.

Not that I have implemented OnItemClick for the ListView and I just want to be able to detect touches on the whole layout.

I've also tried

gameListView = (ListView) findViewById(R.id.gameListView);
gameListView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            System.out.println("Touch test list");
            return true;
        }
    });

although this didn't work either.

Why is the parent layout not getting touch events? How can I get it working?

Answer

Paul Lammertsma picture Paul Lammertsma · Jan 21, 2014

By returning true in onTouch(), you consume the touch event; the parent view's OnTouchListener will not be invoked. The documentation states:

public abstract boolean onTouch (View v, MotionEvent event)

[...]

Returns
True if the listener has consumed the event, false otherwise.

You may instead be interested in having the parent ViewGroup intercept touch events from its children through onInterceptTouchEvent(), as detailed in this guide.