An Android GestureDetectorCompat Class Tutorial

The term “gesture” defines a contiguous sequence of interactions between the touch screen and the user. A typical gesture begins at the point that the screen is first touched and ends when the last finger or pointing device leaves the display surface. When correctly harnessed, gestures can be implemented to communicate between the user and the application. Swiping motions to turn the pages of an eBook or a pinching movement involving two touches to zoom in or out of an image are prime examples of how gestures can interact with an application.

The Android SDK provides mechanisms for the detection of both common and custom gestures within an application. Common gestures involve interactions such as a tap, double tap, long press, or a swiping motion in either a horizontal or a vertical direction (referred to in Android nomenclature as a fling).

This chapter explores using the Android GestureDetector class to detect common gestures performed on the display of an Android device. The next chapter, Android Custom Gesture and Pinch Recognition Tutorials, will cover detecting more complex, custom gestures such as circular motions and pinches.

Implementing Common Gesture Detection

When a user interacts with the display of an Android device, the onTouchEvent() method of the currently active application is called by the system and passed MotionEvent objects containing data about the user’s contact with the screen. This data can be interpreted to identify if the motion on the screen matches a common gesture such as a tap or a swipe. This can be achieved with minimal programming effort by using the Android GestureDetectorCompat class. This class is designed to receive motion event information from the application and trigger method calls based on the type of common gesture, if any, detected.

The basic steps in detecting common gestures are as follows:

 

You are reading a sample chapter from an old edition of the Android Studio Essentials – Kotlin Edition book.

Purchase the fully updated Android Studio Iguana Kotlin Edition of this publication in eBook or Print format.

The full book contains 99 chapters and over 842 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

  1. Declaration of a class which implements the GestureDetector.OnGestureListener interface including the required onFling(), onDown(), onScroll(), onShowPress(), onSingleTapUp() and onLongPress() callback methods. Note that this can be either an entirely new or an enclosing activity class. If double-tap gesture detection is required, the class must also implement the GestureDetector.OnDoubleTapListener interface and include the corresponding onDoubleTap() method.
  2. Creation of an instance of the Android GestureDetectorCompat class, passing through an instance of the class created in step 1 as an argument.
  3. An optional call to the setOnDoubleTapListener() method of the GestureDetectorCompat instance to enable double tap detection if required.
  4. Implementation of the onTouchEvent() callback method on the enclosing activity, which, in turn, must call the onTouchEvent() method of the GestureDetectorCompat instance, passing through the current motion event object as an argument to the method.

Once implemented, the result is a set of methods within the application code that will be called when a gesture of a particular type is detected. The code within these methods can then be implemented to perform any tasks that need to be performed in response to the corresponding gesture.

In the remainder of this chapter, we will work through creating an example project intended to put the above steps into practice.

Creating an Example Gesture Detection Project

This project aims to detect the full range of common gestures currently supported by the GestureDetectorCompat class and to display status information to the user indicating the type of gesture that has been detected.

Select the New Project option from the welcome screen and, within the resulting new project dialog, choose the Empty Views Activity template before clicking on the Next button.

Enter CommonGestures into the Name field and specify com.ebookfrenzy.commongestures as the package name. Before clicking the Finish button, change the Minimum API level setting to API 26: Android 8.0 (Oreo) and the Language menu to Kotlin.

 

You are reading a sample chapter from an old edition of the Android Studio Essentials – Kotlin Edition book.

Purchase the fully updated Android Studio Iguana Kotlin Edition of this publication in eBook or Print format.

The full book contains 99 chapters and over 842 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

Adapt the project to use view binding as outlined in An Overview of Android View Binding.

Once the new project has been created, navigate to the app -> res -> layout -> activity_main.xml file in the Project tool window and double-click on it to load it into the Layout Editor tool.

Within the Layout Editor tool, select the “Hello, World!” TextView component and, in the Attributes tool window, enter gestureStatusText as the ID. Finally, set the textSize to 20sp and enable the bold textStyle:

Figure 35-1

Implementing the Listener Class

As previously outlined, it is necessary to create a class that implements the GestureDetector.OnGestureListener interface and, if double tap detection is required, the GestureDetector.OnDoubleTapListener interface. While this can be an entirely new class, it is also perfectly valid to implement this within the current activity class. Therefore, we will modify the MainActivity class to implement these listener interfaces for this example. Edit the MainActivity.kt file so that it reads as follows:

package com.ebookfrenzy.commongestures
 
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.GestureDetector
import android.view.MotionEvent
.
.  
class MainActivity : AppCompatActivity(), 
   GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener
{
.
.Code language: JavaScript (javascript)

Declaring that the class implements the listener interfaces mandates that the corresponding methods also be implemented in the class:

 

You are reading a sample chapter from an old edition of the Android Studio Essentials – Kotlin Edition book.

Purchase the fully updated Android Studio Iguana Kotlin Edition of this publication in eBook or Print format.

The full book contains 99 chapters and over 842 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

class MainActivity : AppCompatActivity(), 
   GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener
{
.
.
    override fun onDown(event: MotionEvent): Boolean {
        binding.gestureStatusText.text = "onDown"
        return true
    }
 
    override fun onFling(event1: MotionEvent?, event2: MotionEvent,
                         velocityX: Float, velocityY: Float): Boolean {
        binding.gestureStatusText.text = "onFling"
        return true
    }
 
    override fun onLongPress(event: MotionEvent) {
        binding.gestureStatusText.text = "onLongPress"
    }
 
    override fun onScroll(e1: MotionEvent?, e2: MotionEvent,
                          distanceX: Float, distanceY: Float): Boolean {
        binding.gestureStatusText.text = "onScroll"
        return true
    }
 
    override fun onShowPress(event: MotionEvent) {
        binding.gestureStatusText.text = "onShowPress"
    }
 
    override fun onSingleTapUp(event: MotionEvent): Boolean {
        binding.gestureStatusText.text = "onSingleTapUp"
        return true
    }
 
    override fun onDoubleTap(event: MotionEvent): Boolean {
        binding.gestureStatusText.text = "onDoubleTap"
        return true
    }
 
    override fun onDoubleTapEvent(event: MotionEvent): Boolean {
        binding.gestureStatusText.text = "onDoubleTapEvent"
        return true
    }
 
    override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
        binding.gestureStatusText.text = "onSingleTapConfirmed"
        return true
    }
}Code language: Kotlin (kotlin)

Note that many of these methods return true. This indicates to the Android Framework that the method has consumed the event and does not need to be passed to the next event handler in the stack.

Creating the GestureDetectorCompat Instance

With the activity class now updated to implement the listener interfaces, the next step is to create an instance of the GestureDetectorCompat class. Since this only needs to be performed once at the point that the activity is created, the best place for this code is in the onCreate() method. Since we also want to detect double taps, the code also needs to call the setOnDoubleTapListener() method of the GestureDetectorCompat instance:

.
.
import androidx.core.view.GestureDetectorCompat
 
class MainActivity : AppCompatActivity(), GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener
{
    private lateinit var binding: ActivityMainBinding
    var gDetector: GestureDetectorCompat? = null
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
 
        this.gDetector = GestureDetectorCompat(this, this)
        gDetector?.setOnDoubleTapListener(this)
    }
.
.Code language: Kotlin (kotlin)

Implementing the onTouchEvent() Method

If the application were to be compiled and run at this point, nothing would happen if gestures were performed on the device display. This is because no code has been added to intercept touch events and to pass them through to the GestureDetectorCompat instance. To achieve this, it is necessary to override the onTouchEvent() method within the activity class and implement it such that it calls the onTouchEvent() method of the GestureDetectorCompat Detecting Common Gestures Using the Android Gesture Detector Class

instance. Remaining in the MainActivity.kt file, therefore, implement this method so that it reads as follows:

override fun onTouchEvent(event: MotionEvent): Boolean {
    this.gDetector?.onTouchEvent(event)
    // Be sure to call the superclass implementation
    return super.onTouchEvent(event)
}Code language: Kotlin (kotlin)

Testing the Application

Compile and run the application on either a physical Android device or an AVD emulator. Once launched, experiment with swipes, presses, scrolling motions, and double and single taps. Note that the text view updates to reflect the events as illustrated in Figure 35-2:

 

You are reading a sample chapter from an old edition of the Android Studio Essentials – Kotlin Edition book.

Purchase the fully updated Android Studio Iguana Kotlin Edition of this publication in eBook or Print format.

The full book contains 99 chapters and over 842 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

Figure 35-2

Summary

Any physical contact between the user and the touchscreen display of a device can be considered a “gesture”. Lacking the physical keyboard and mouse pointer of a traditional computer system, gestures are widely used as a method of interaction between the user and the application. While a gesture can comprise just about any sequence of motions, there is a widely used set of gestures with which users of touchscreen devices have become familiar. Some of these so-called “common gestures” can be easily detected within an application by using the Android Gesture Detector classes. In this chapter, the use of this technique has been outlined both in theory and through the implementation of an example project.

Having covered common gestures in this chapter, the next chapter will look at detecting a wider range of gesture types, including the ability to design and detect your own gestures.