Using onTouchEvent() and View.OnTouchListener Interface with MotionEvent to Detect Common Gestures Like Tap and Swipes on Android

Touch gestures like tapping, swiping vertically/horizontally, panning, etc. occurs when a user places one or more fingers on the screen and by the time the last finger looses contact, the entire pattern of finger movements is interpreted as a particular gesture by your android application. First all the relevant data of touch events are gathered and then they’re interpreted to see which gestures they match and the pertaining actions are executed as specified in the code.

Using onTouchEvent() to Detect Gestures

We’ll look at how to use the onTouchEvent() method to intercept the touch events in an Activity or a View. This method is called several times as the pressure, size, position, etc. of the touch event changes or even when a new finger is put on the touch screen.

What's the one thing every developer wants? More screens! Enhance your coding experience with an external monitor to increase screen real estate.

Overriding the Activity onTouchEvent()

Here’s how we override the onTouchEvent() method of the Activity to detect various touch events:

private String TAG = GestureActivity.class.getSimpleName();
float initialX, initialY;

@Override
public boolean onTouchEvent(MotionEvent event) {
    //mGestureDetector.onTouchEvent(event);

    int action = event.getActionMasked();

    switch (action) {

        case MotionEvent.ACTION_DOWN:
            initialX = event.getX();
            initialY = event.getY();

            Log.d(TAG, "Action was DOWN");
            break;

        case MotionEvent.ACTION_MOVE:
            Log.d(TAG, "Action was MOVE");
            break;

        case MotionEvent.ACTION_UP:
            float finalX = event.getX();
            float finalY = event.getY();

            Log.d(TAG, "Action was UP");

            if (initialX < finalX) {
                Log.d(TAG, "Left to Right swipe performed");
            }

            if (initialX > finalX) {
                Log.d(TAG, "Right to Left swipe performed");
            }

            if (initialY < finalY) {
                Log.d(TAG, "Up to Down swipe performed");
            }

            if (initialY > finalY) {
                Log.d(TAG, "Down to Up swipe performed");
            }

            break;

        case MotionEvent.ACTION_CANCEL:
            Log.d(TAG,"Action was CANCEL");
            break;

        case MotionEvent.ACTION_OUTSIDE:
            Log.d(TAG, "Movement occurred outside bounds of current screen element");
            break;
    }

    return super.onTouchEvent(event);
}

The MotionEvent class has 2 methods that can be used to get the action being performed:

  • getAction() – Returns the kind of action being performed as a packed integer that contains the action code/constant (like ACTION_MOVE) and pointer index (which finger for multi-touch). For single touches it’s safe to use this function as there’s only one finger involved, hence no need to store the pointer index.
  • getActionMasked() – Returns the action performed without the pointer index information unlike getAction(). The associated pointer index can be fetched by calling getActionIndex().

To go through an in-depth difference between the 2 methods, there are some decent SO answers that’ll suffice.

getX() and getY() are used to get the X/Y coordinates of the touch interaction.

Getting the touch pressure is also damn easy with getPressure().

Capturing Touch Events on a View

We can use onTouchEvent() on a View by subclassing it to create a custom View like this:

class CustomImageView extends ImageView {

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getActionMasked();

        Log.d(TAG, String.valueOf(action));

        return super.onTouchEvent(event);
    }
}

Then programatically create an object of this class and insert into the layout is a way of having CustomImageView views. But it’s all a little messy to override the way in which touch events are handled by a specific View and not really required. A much better alternative is to attach a View.OnTouchListener object to the View object using setOnTouchListener().

ImageView imageView = (ImageView) findViewById(R.id.imageView1);
imageView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {

        // have same code as onTouchEvent() (for the Activity) above

        int action = event.getActionMasked();

        Log.d(TAG, String.valueOf(action));

        return true;
    }
});

Conclusion

That’s all! Now you know how to detect basic gestures like tap and swipes (interpret with directions) on an Activity or a particular View pretty easily. If your app uses common gestures like flings/swipes, single/double taps, long press, etc. then you can make use of the GestureDetector class which does all the intricate processing for these common gestures by itself behind the scenes.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Author: Rishabh

Rishabh is a full stack web and mobile developer from India. Follow me on Twitter.

2 thoughts on “Using onTouchEvent() and View.OnTouchListener Interface with MotionEvent to Detect Common Gestures Like Tap and Swipes on Android”

  1. Hello sir
    I want to set click listner on adapter flipper view and get item value from view so please help me which method will use and how to impliment

Leave a Reply

Your email address will not be published. Required fields are marked *