Most of the Android UI elements already come with some easy way to detect and handle touch events. For example have a look to the following code:
TextView myTextView = (TextView) findViewById(R.id.myTextView);
myTextView.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Log.i("MyExample", "A Long Click has been detected");
return true;
}
});
When you touch the myTextView long enough, you will see in the logs the print A Long Click has been detected.
In other cases, however, in which this kind of solution is not available, or doesn’t fit your needs. For example
- the UI element does not let you set a listener for the action you want to detect. You can’t set a double click listener for a
TextView widget, and other elements, like the Map Overlay, can only detect a very limited set of actions;
- you need more information about the action, e.g. the exact position of the pointer (finger).
In those cases the best solution is to use the GestureDetector.
The GestureDetector works a little bit differently from what you may be used to. In fact it is not listening to the actions: it is in charge of translating what a widget or another UI element sees as a generic touch event, to a more specific action. Fortunately any UI element gives you some way to handle a generic touch event.
Let’s see a complete example of how to put the GestureDetector to work within a simple Activity class.
package com.example;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
public class GestureDetectorExample extends Activity {
static private String TAG = "GestureDetectorExample";
private GestureDetector mGestureDetector;
private TextView mTextView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView = (TextView) findViewById(R.id.myTextView);
mTextView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
@Override
public void onLongPress(MotionEvent e) {
Log.d(TAG, "Long Press event");
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.d(TAG, "Double Tap event");
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
});
mGestureDetector.setIsLongpressEnabled(true);
}
}
Let’s see now what happens in the example:
- a
TouchListener is set for the TextView;
- a
GestureDetector object is instantiated, with a reference to an object which implements the OnGestureListener interface (we’ll come back on this later);
- when a touch event is detected by the
TextView, the method onTouch is called;
- the method
onTouch calls the GestureDetector and pass it the MotionEvent, an object containing the information needed by the GestureDetector to recognize the different touch events;
- the
GestureDetector uses the MotionEvent object to identify the touch events;
- once identified the type of the event, the
GestureDetector calls the appropriate method of the OnGestureListener (double tap, long press, etc.).
It’s time to run the program and perform some long tap, or double click on the TextView while keeping an eye on the logs in the LogCat.

A couple of notes.
- The
onDown method.
If you try to remove it you will see that the onDoubleTap method is not called anymore. Same if the onDown method returns false. So keep in mind that to make onDoubleTap work you must have a onDown method returning true.
SimpleOnGestureListener class vs OnGestureListener interface
In the example, the SimpleOnGestureListener class is used. It is a commodity class that implements the OnGestureListener interface. If you decide to implement the OnGestureListener interface you must implement all its methods, even you only need to handle one event. When you inherit from the SimpleOnGestureListener, instead, you will only override the methods you need.
Let’s now see another example, this time using the Overlay from the Google Maps API.
package com.example;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
public class GestureDetectExampleMap extends MapActivity {
private static String TAG = "GestureDetectorExampleMap";
MapView mMapView;
GestureDetector mGestureDetector;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mMapView = (MapView) findViewById(R.id.MapView);
mMapView.getOverlays().add(new Overlay() {
@Override
public boolean onTouchEvent(MotionEvent e, MapView mapView) {
mGestureDetector.onTouchEvent(e);
return super.onTouchEvent(e, mapView);
}
});
mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
@Override
public void onLongPress(MotionEvent e) {
Log.d(TAG, "Long Press event");
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.d(TAG, "Double Tap event");
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
});
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
}
The GestureDetector part is exactly the same, but in this case the GestureDetector.onTouchEvent is called by the map Overlay, and unlike a generic View element, there is no need to instantiate a Listener for it.
A touch event will go through the following steps:
- the touch event triggers the
onTouchEvent inside the Overlay;
- the
onTouchEvent of the Overlay calls the correspondent method of the GestureDetector and pass it the MotionEvent, an object containing the information needed by the GestureDetector to recognize the different touch events;
- the
GestureDetector uses the MotionEvent object to identify the touch events;
- once identified the type of the event, the
GestureDetector calls the appropriate method of the OnGestureListener (double tap, long press, etc.).
For lazy people only: download a zip file with the two examples.
It may be useful for you to have a look to a few articles that I also consulted before writing this article:
Feel free to comment to ask any question, correct any mistake or suggest any improvement.