Flutter Gestures

Gestures are the feature in Flutter which allows us to interact with the app. Generally,it is defined as any physical action or movement of the user with the intention of specific control of the device. Examples of gestures are:

  • We slide your finger across the screen of a locked device to unlock it.
  • Tapping a mobile screen, and
  • Pinching the screen to zoom on some sections.
    • We use gestures in everyday life to interact with phones.

      Flutter divides the gestures into two different type of layers,as below:
      1. Pointers
      2. Gestures

      Pointers

      Pointers are the first layer which represents the raw data of the user interaction. It contains events, which describe the location and movement of the touches and mouse movement across the screens. Flutter doesn’t have any mechanism which can be used to cancel or stop the pointer-events from being dispatched further. Flutter provides us with a Listener widget which listens for pointer-events directly from the layers.

      The pointer-events are categorized into four events:
      1. PointerDownEvents
      2. PointerMoveEvents
      3. PointerUpEvents
      4. PointerCancelEvents

      PointerDownEvents: PointerDownEvents tells the pointer to check the screen at a pointed location.

      PointerMoveEvents: PointerMoveEvents tells the pointer to move from one location to another location on the screen.

      PointerUpEvents: PointerUpEvents tells the pointer to stop checking the screen.

      PointerCancelEvents: PointerCancelEvents is sent when the pointer interaction is canceled.

      Gestures

      This is the second layer that represents the semantic actions performed by the user such as tapping the screen, dragging, and scaling, which are recognized using multiple pointer events. This layer is also able to dispatch multiple events which correspond to the gesture lifecycle like drag start, drag update, and drag end. Some of the popularly used gesture are listed below:

      Tap: Tap is the event when a user touches the screen in a tapping action. Events associated with this gesture:

      • onTapDown
      • onTapUp
      • onTap
      • onTapCancel

      Double Tap: When you tap the screen twice this event occurs. Events associated with this gesture:

      • onDoubleTap

      Drag: When a user touches the surface of the screen and moves it from one location to another location and then releases them.

      Drag can be categorized into two types:
      1. Horizontal Drag: We move the pointer in the horizontal direction. It contains the following events:
        • onHorizontalDragStart
        • onHorizontalDragUpdate
        • onHorizontalDragEnd
      2. Vertical Drag: We move the pointer in the vertical direction. It contains the following events:
        • onVerticalDragStart
        • onVerticalDragStart
        • onVerticalDragStart

      Long Press: LongPress is the event which occurs when we touch the surface of the screen for a long time at a particular location. This gesture contains the following events:

      • onLongPress

      Pan: LongPress is the event which occurs when we touch the surface of the screen with a fingertip, we can move in any direction without releasing. This gesture contains the following events:

      • onPanStart
      • onPanUpdate
      • onPanEnd

      Pinch: It means pinching the surface of the screen using two fingers to zoom into or out on a screen.

      Gesture Detector

      Flutter provides widgets that provide excellent support for different types of gestures using the GestureDetector widget. The GestureWidget is an invisible widget, which is used primarily for detecting the gesture. GestureDetector is a stateless widget that contains various parameters in its constructor for different types of events.

      In some situations, we can use multiple gesture detectors at a particular location on the screen, and the framework determines which gesture should be called from the group. GestureDetector widget decides which gesture is to be used and the gesture is recognized based on which of the callbacks are non-null.

      Let us learn how to use these gestures in our application with a simple onTap() event and find out how the GestureDetector uses it. Here, we are creating a widget, in which we add the onTap() function to it.

      Now, let’s create a new Flutter project and add the following code in the main.dart file.

      import 'package:flutter/material.dart';
      
      void main() {
        runApp(MyApp());
      }
      class MyApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            title: 'Gestures Example',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: MyHomePage(title: 'Flutter Demo Home Page'),
          );
        }
      }
      class MyHomePage extends StatelessWidget {
        MyHomePage({Key key, this.title}) : super(key: key);
      
        final String title;
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: Text(this.title),
            ),
            body: Center(
              child: GestureDetector(
                onTap: () => print('tapped'),
                child: Container(
                  padding: EdgeInsets.all(10.0),
                  decoration: BoxDecoration(
                    color: Colors.lightGreen,
                    borderRadius: BorderRadius.circular(15.0),
                  ),
                  child: Text('Text'),
                ),
              ),
            ),
         
         );
        }}
      
      Output

      flutter-gesture-detector

      In the above image, you can see a green box with rounded edges on the center of the screen containing text. When we tap on this button, and You can check the output on the debug console.

      Flutter also provides a set of widgets which allows us to do specific and advanced gestures.

      These widgets are given below:

      Dismissible: Dismissible widget supports the flick gesture to dismiss this widget.

      Draggable: Draggable widget supports drag gestures to move the widget.

      LongPressDraggable: LongPressDraggable widget supports a drag gesture to move a widget along with its parent widget.

      DragTarget: DragTarget widget can accept any Draggable widget.

      IgnorePointer: IgnorePointer widget hides the widget and its children from the gesture detection process.

      AbsorbPointer: AbsorbPointer widget stops the gesture detection process itself. Due to this, any overlapping widget cannot participate in the gesture detection process, and thus, no event is raised.

      Scrollable: Scrollable widget supports scrolling of the content which is available inside the widget.

      Multiple Gesture Example

      In this section, we are going to learn how multiple gestures work by using the below applications. Demo app consists of two containers, parent and child. Here, everything is handled is used manually by using ‘RawGestureDetector’ and custom ‘GestureRecognizer’ The custom GestureRecognizer provide ‘MultipleGestureRecognizer’ property to the gesture list and create a ‘GestureRecognizerFactoryWithHandlers’. Next, when the onTap() event is called, it prints text to the console.

      import 'package:flutter/gestures.dart';
      import 'package:flutter/material.dart';
      
      void main() {
        runApp(MyApp());
      }
      
      class MyApp extends StatelessWidget {
        // This widget is the root of your application.
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            title: 'Gestures Example',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: MyHomePage(title: 'Flutter Demo Home Page'),
          );
        }
      }
      
      class MyHomePage extends StatelessWidget {
        MyHomePage({Key key, this.title}) : super(key: key);
      
        final String title;
      
        @override
        Widget build(BuildContext context) {
          return RawGestureDetector(
            gestures: {
              MultipleGestureRecognizer:
                  GestureRecognizerFactoryWithHandlers(
                () => MultipleGestureRecognizer(),
                (MultipleGestureRecognizer instance) {
                  instance.onTap = () => print('parent');
                },
              )
            },
            behavior: HitTestBehavior.opaque,
           
       //Parent Container
            child: Container(
              color: Colors.green,
              child: Center(
                //Now, wraps the second container in RawGestureDetector
                child: RawGestureDetector(
                  gestures: {
                    MultipleGestureRecognizer: GestureRecognizerFactoryWithHandlers<
                        MultipleGestureRecognizer>(
                      () => MultipleGestureRecognizer(), //constructor
                      (MultipleGestureRecognizer instance) {
                        //initializer
                        instance.onTap = () => print('nested');
                      },
                    )
                  },
                  //Creates the nested container within the first.
                  child: Container(
                    color: Colors.deepOrange,
                    width: 250.0,
                    height: 350.0,
                  ),
                ),
              ),
            ),
          );
        }
      }
      
      class MultipleGestureRecognizer extends TapGestureRecognizer {
        @override
        void rejectGesture(int pointer) {
          acceptGesture(pointer);
        }
      }
      
      Output

      When you run the app, it will give the following output.

      multiple-gesture-example

      Next, tap on the orange box, the following output appears on your console.

      • nested
      • parent
Subscribe Now