androidtouchlistenerclickableripple

Android: How to detect touch on clickable RelativeLayout?


I have a custom layout "MyLayout" which extends RelativeLayout and inflates my_layout.xml:

public class MyLayout extends RelativeLayout {

    // the constructors are all calling init(context);

    private void init(Context context) {
        if (context != null) {
            LayoutInflater.from(context).inflate(R.layout.my_layout, this);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        System.out.println("touched");
        return super.onTouchEvent(event);
    }
}

Here is my_layout.xml which has a ripple animation:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/relative_layout"
        android:clickable="false"
        android:background="@drawable/ripple_background"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

Now here is what happens when i change the value of android:clickable

android:clickable="false" android:clickable="true"
ripple animation won't show up ripple animation works as intended
onTouchEvent(MotionEvent) will be called on touch onTouchEvent(MotionEvent) is never called

How can i make both the ripple animation visible as well as onTouchEvent(MotionEvent) be called on touch?


Solution

  • Thanks to zoomega, who showed me this question: Activity's onTouchEvent() is not being called while clicking on Button.

    I have adjusted my code as follows:

    public class MyLayout extends RelativeLayout {
    
        // the constructors are all calling init(context);
    
        private void init(Context context) {
            if (context != null) {
                LayoutInflater.from(context).inflate(R.layout.my_layout, this);
            }
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            super.dispatchTouchEvent(ev); // Necessary in order to trigger the ripple animation!
            System.out.println("touched"); // The logic here (e.g. GestureDetector)
            return true;
        }
    }
    

    This way, both the ripple effect is displayed and dispatchTouchEvent(MotionEvent) is called.