Android Pinch Gesture Detection Tutorial using Android Studio
Before moving on from touch handling in general and gesture recognition in particular, the last topic of this chapter is that of handling pinch gestures. Whilst it is possible to create and detect a wide range of gestures using the steps outlined in the previous sections of this chapter it is, in fact, not possible to detect a pinching gesture (where two fingers are used in a stretching and pinching motion, typically to zoom in and out of a view or image) using the techniques discussed so far.
The simplest method for detecting pinch gestures is to use the Android ScaleGestureDetector class. In general terms, detecting pinch gestures involves the following three steps:
1. Declaration of a new class which implements the SimpleOnScaleGestureListener interface including the required onScale(), onScaleBegin() and onScaleEnd() callback methods.
2. Creation of an instance of the ScaleGestureDetector class, passing through an instance of the class created in step 1 as an argument.
3. Implementing the onTouchEvent() callback method on the enclosing activity which, in turn, calls the onTouchEvent() method of the ScaleGestureDetector class.
In the remainder of this chapter, we will create a very simple example designed to demonstrate the implementation of pinch gesture recognition.
A Pinch Gesture Example Project
Within Android Studio, create a new Android application project named PinchExample with appropriate, module, package name and SDK settings. Request the creation of a blank activity and, when prompted to do so, set the Activity Name to PinchExampleActivity and the Layout Name to activity_pinch_example.
Within the activity_pinch_example.xml file, locate the TextView object and double click on it to change the ID to @+id/myTextView.
Locate and load the PinchExampleActivity.java file into the Android Studio editor and modify the file as follows:
package com.ebookfrenzy.pinchexample.pinchexample; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener; import android.widget.TextView; public class PinchExampleActivity extends ActionBarActivity { TextView scaleText; ScaleGestureDetector scaleGestureDetector; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_pinch_example); scaleText = (TextView)findViewById(R.id.myTextView); scaleGestureDetector = new ScaleGestureDetector(this, new MyOnScaleGestureListener()); } @Override public boolean onTouchEvent(MotionEvent event) { scaleGestureDetector.onTouchEvent(event); return true; } public class MyOnScaleGestureListener extends SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { float scaleFactor = detector.getScaleFactor(); if (scaleFactor > 1) { scaleText.setText("Zooming Out"); } else { scaleText.setText("Zooming In"); } return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } } . . . }
The code begins by declaring TextView and ScaleGestureDetector variables. A new class named MyOnScaleGestureListener is declared which extends the Android SimpleOnScaleGestureListener class. This interface requires that three methods (onScale(), onScaleBegin() and onScaleEnd()) be implemented. In this instance the onScale() method identifies the scale factor and displays a message on the text view indicating the type of pinch gesture detected.
Within the onCreate() method, a reference to the text view object is obtained and assigned to the scaleText variable. Next, a new ScaleGestureDetector instance is created, passing through a reference to the enclosing activity and an instance of our new MyOnScaleGestureListener class as arguments. Finally, an onTouchEvent() callback method is implemented for the activity, which simply calls the corresponding onTouchEvent() method of the ScaleGestureDetector object, passing through the MotionEvent object as an argument.
Compile and run the application on a physical Android device and perform pinching gestures on the screen, noting that the text view displays either the zoom in or zoom out message depending on the pinching motion.
Summary
A gesture is essentially the motion of points of contact on a touch screen involving one or more strokes and can be used as a method of communication between user and application. Android allows gestures to be designed using the Gesture Builder application. Once created, gestures can be saved to a gestures file and loaded into an activity at application runtime using the GestureLibrary.
Gestures can be detected on areas of the display by overlaying existing views with instances of the transparent GestureOverlayView class and implementing an OnGesturePerformedListener event listener. Using the GestureLibrary, a ranked list of matches between a gesture performed by the user and the gestures stored in a gestures file may be generated, using a prediction score to decide whether a gesture is a close enough match.
Pinch gestures may be detected through the implementation of the ScaleGestureDetector class, an example of which was also provided in this chapter.