Android Touch Event Detection for both parent and child viewing at the same time

The layout of my application is currently in use:

       LinearLayout
            ----Button
               ----ScrollView
                  ----RelativeLayout
                     ----EditText

      

I created one transparent LinearLayout over all of these, implemented OnTouchListener and inside OnTouch (), returned false. In this way, all controls are floated below the children. But in LinearLayout I cannot handle ACTION_MOVE actions as MotionEvent object is not used by this layout. Is there a way to detect all touch events in both parent and child views?

+3


source to share


2 answers


In my experience, the method dispatchTouchEvent()

should not be overridden as it is difficult to control. My suggestion is a method onInterceptTouchEvent()

. This option is not supported for Android overrides. You can capture it by creating your own view, here is the code snippet that comes from the RelativeLayout:

public class InterceptTouchRelativeLayout extends RelativeLayout{

public interface OnInterceptTouchListener{
    boolean onInterceptTouch(MotionEvent ev);
}

private OnInterceptTouchListener onInterceptTouchListener;

public InterceptTouchRelativeLayout(Context context) {
    super(context);
}

public InterceptTouchRelativeLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public InterceptTouchRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return onInterceptTouchListener.onInterceptTouch(ev);
}

public void setOnInterceptTouchListener(OnInterceptTouchListener onInterceptTouchListener) {
    this.onInterceptTouchListener = onInterceptTouchListener;
}

      

}

And use it as usual,



myView.setOnInterceptTouchListener(new InterceptTouchRelativeLayout.OnInterceptTouchListener() {
        @Override
        public boolean onInterceptTouch(MotionEvent ev) {
            switch (ev.getAction()){
                case MotionEvent.ACTION_DOWN:
                    // Parent didn't steal this touch event if return false this case.
                    return false;

                case MotionEvent.ACTION_MOVE:
                    // Parent didn't steal this touch event if return false this case.
                    return false;

                case MotionEvent.ACTION_UP:
                    // Parent didn't steal this touch event if return false this case. However, please notice, it too late for the parent to steal this touch event at this time, it won't work anymore.
                    return true;
            }

            return false;
        }
    });

      

Anyway, my advice is to study more the flow of sensory events in this group of views. And this is an explanation of how it onInterceptTouchEvent()

will work for your purpose:

  • When a parent is touched at the position where its child is, it will be called onInterceptTouchEvent()

    , if we return false in ACTION_DOWN, it will consider that the parent has not yet stolen this touch event and check if its child has been implemented. onTouch()

    ... This way, as long as the child does not call requestDisallowInterceptTouchEvent(true)

    , the parents can handle that touch event in onInterceptTouchEvent()

    , and the child can handle the same touch event in their own eventonTouch()

    . However, sometimes you need to consider handling the onTouch()

    parent event if there are no children handling the touch event for the parent to take care of.
+2


source


This can be done by overriding dispatchTouchEvent

in the layout.

public class MyFrameLayout extends LinearLayout {
    @Override
    public boolean dispatchTouchEvent(MotionEvent e) {
        // do what you need to with the event, and then...
        return super.dispatchTouchEvent(e);
    }
}

      

Then use this layout instead of your regular FrameLayout:



    <com.example.android.MyFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="10dip"
        android:id="@+id/rootview">

  ...

      

You can also skip the super challenge entirely if you need to prevent the views from receiving the event, but I think that would be rare.

This answer is based on Romain guy's answer link .

+1


source







All Articles