Android: Detecting Double Tap Events
Posted by Dimitri | Jul 6th, 2011 | Filed under Featured, Programming
This Android tutorial explains how to create an Activity that “listens” to double tap events. Doing that isn’t as trivial as getting a single tap from the screen, however writing a code that registers when the screen has been touched twice isn’t complex either. The example featured in this post works on the emulator and on a real Android device.
To implement the double tap, some classes and interfaces are going to be needed, but it’s best to show the example Activity code before explaining each one of them:
package fortyonepost.com.doubletap; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.widget.TextView; import android.view.GestureDetector; import android.view.GestureDetector.OnDoubleTapListener; import android.view.GestureDetector.OnGestureListener; //Implement this interface to be notified when a gesture occurs public class DoubleTapActivity extends Activity implements OnGestureListener { //creates a Gesture Detector private GestureDetector gd; //a TextView object private TextView tvTap; //another TextView object private TextView tvTapEvent; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //get the TextView from the XML file tvTap = (TextView)findViewById(R.id.tvTap); //get the other TextView from the XML file tvTapEvent = (TextView)findViewById(R.id.tvTapEvent); //initialize the Gesture Detector gd = new GestureDetector(this); //set the on Double tap listener gd.setOnDoubleTapListener(new OnDoubleTapListener() { @Override public boolean onDoubleTap(MotionEvent e) { //set text color to green tvTap.setTextColor(0xff00ff00); //print a confirmation message tvTap.setText("The screen has been double tapped."); return false; } @Override public boolean onDoubleTapEvent(MotionEvent e) { //if the second tap hadn't been released and it's being moved if(e.getAction() == MotionEvent.ACTION_MOVE) { //set text to blue tvTapEvent.setTextColor(0xff0000ff); //print a confirmation message and the position tvTapEvent.setText("Double tap with movement. Position:\n" + "X:" + Float.toString(e.getRawX()) + "\nY: " + Float.toString(e.getRawY())); } else if(e.getAction() == MotionEvent.ACTION_UP)//user released the screen { tvTapEvent.setText(""); } return false; } @Override public boolean onSingleTapConfirmed(MotionEvent e) { //set text color to red tvTap.setTextColor(0xffff0000); //print a confirmation message and the tap position tvTap.setText("Double tap failed. Please try again."); return false; } }); } @Override public boolean onTouchEvent(MotionEvent event) { return gd.onTouchEvent(event);//return the double tap events } @Override public boolean onDown(MotionEvent e) { return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } }
Don’t worry, the above code is long, but the part related to the double tap detection is only up to the 86th line. The first important thing to watch out for in this code are the packages that are being imported, such as the GestureDetector.OnDoubleTapListener and the GestureDetector.OnGestureListener interfaces. The first one is responsible for registering double tap events. The second, is a generic touch screen event listener, that can intercept any kind of touch event, such as presses, long presses, flings and most importantly, double taps (lines 8 and 9).
Right after that, the class DoubleTapActivity is declared. It inherits the Activity class, and implements OnGestureListener interface. Because of this interface, we have to override a lot of methods, that goes from line 88 through line 121. In the above example, they will just return their default values. The main reason why this interface was implemented will be explained when we see the attributes of this class.
Speaking of which, there are three attributes in this class: two TextView objects and a GestureDetector object, declared at lines 15 through 20. The TextView objects are going to be initialized with TextView elements from the main.xml interface file (lines 30 and 32). The GestureDetector is being initialized by passing a OnGestureListener to the GestureDetector constructor. Since the above class is implementing the OnGestureListener interface, it’s possible to pass “this” as the parameter to the constructor (line 35).
And then, all it’s left to do is to call the setOnDoubleTapListener method from the gd object, passing a new OnDoubleTapListener interface (line 38). This interface requires the implementation of three methods: onDoubleTap(), onDoubleTapEvent() and onSingleTapConfirmed(). They all take a MotionEvent object as the single parameter.
The first one, onDoubleTap() is called when the system detects a double tap. It doesn’t return any additional information, such as position and follow-up move events. In this example, every time the screen is double tapped, one of the TextView object’s text is set to green and a message is displayed confirming the double tap (lines 41 through 47).
The second method, onSingleTapConfirmed() works just like the OnDoubleTap(), except a double tap event details can be intercepted, such as determining if the user is still holding the screen after the second tap, move events, tap position and much more. In the above code, one of the TextView object’s text is set to blue and a message displays the X and Y coordinates of the double tap event only while the user is still pressing and dragging his/her finger through the surface of the screen. After the user releases the screen, the text is set to a empty sequence of characters, so it disappears (lines 51 through 68).
The last and the third of the OnDoubleTapListener method is the onSingleTapConfirmed(). It executes every time the GestureDetector knows that the tap event won’t be followed by another one, causing a double-tap event. In other words, this method is called when a tap to the screen occurs and the system has determined that it should not threat the next and current taps as a single double-tap event, since the interval that passed between the two wasn’t short enough. In this example, one of the TextView object’s text is set to red and a message is displayed telling the user that he/she has failed to double tap the screen (lines 71 though 77).
Finally, the last thing to do is to set these events as the return of the onTouchEvent() method. By doing so, every time the screen captures a touch event while the DoubleTapActivity is active, the GestureDetector we have set to listen to double taps (gd) is called (lines 82 through 86).
And that’s it!
Here’s an Eclipse project with everything that has been explained here:
Downloads
Don’t forget to comment!
Nice one. Looking for this piece…
thanks a lot of ! I used thread and timer to get double tap and single tap, but it is very complex ! your example is very easy to understand !
Thanks so much again ! :)
Thanks, very helpful.
Very Good Example…..
Working Perfectly….
keep it up…
hey how to change to button in this situation ah ?
I guess that you could create a class that inherits from Button and do the same as described above.
Nice example.