Flutter - Using GestureDetector Examples

This tutorial shows you how to use GestureDetector in Flutter.

If you need to detect what kind of gesture is happening on a widget, the easiest way is by wrapping the widget as the child of GestureDetector. It's a StatelessWidget that can have a lot of callback functions each for different types of gestures. It supports various types of gestures such as tap, secondary tap, long press, vertical/horizontal drag, pan, and scale. Below are the examples of how to use Flutter's GestureDetector along with explanations for each supported gesture type.

Using GestureDetector

Flutter's GestureDetector constructor has a lot of parameters. Most of them are callback functions each for handling a specific gesture tpe. There is no required parameter.

  GestureDetector({
    Key key,
    this.child,
    this.onTapDown,
    this.onTapUp,
    this.onTap,
    this.onTapCancel,
    this.onSecondaryTap,
    this.onSecondaryTapDown,
    this.onSecondaryTapUp,
    this.onSecondaryTapCancel,
    this.onDoubleTap,
    this.onLongPress,
    this.onLongPressStart,
    this.onLongPressMoveUpdate,
    this.onLongPressUp,
    this.onLongPressEnd,
    this.onSecondaryLongPress,
    this.onSecondaryLongPressStart,
    this.onSecondaryLongPressMoveUpdate,
    this.onSecondaryLongPressUp,
    this.onSecondaryLongPressEnd,
    this.onVerticalDragDown,
    this.onVerticalDragStart,
    this.onVerticalDragUpdate,
    this.onVerticalDragEnd,
    this.onVerticalDragCancel,
    this.onHorizontalDragDown,
    this.onHorizontalDragStart,
    this.onHorizontalDragUpdate,
    this.onHorizontalDragEnd,
    this.onHorizontalDragCancel,
    this.onForcePressStart,
    this.onForcePressPeak,
    this.onForcePressUpdate,
    this.onForcePressEnd,
    this.onPanDown,
    this.onPanStart,
    this.onPanUpdate,
    this.onPanEnd,
    this.onPanCancel,
    this.onScaleStart,
    this.onScaleUpdate,
    this.onScaleEnd,
    this.behavior,
    this.excludeFromSemantics = false,
    this.dragStartBehavior = DragStartBehavior.start,
  })

Usually, you need to have a Widget passed as child and pass at least one callback function depending on what gestures types you want to handle.

  GestureDetector(
    onTap: () {
      print('onTap');
      Feedback.forTap(context);
    },
    onLongPress: () {
      print('onLongPress');
      Feedback.forLongPress(context);
    },
    child: RaisedButton(
      child: Text('Click'),
    ),
  )

 

Handling Specific Gestures

Below are the examples of callback functions for each gesture type. Some of them have a parameter that allows you to get the detail of the gesture.

Using onTapDown

onTapDown is triggered when a pointer has started to contact the screen at a particular location. It doesn't wait until the tap gesture wins. It has a parameter of type TapDownDetails.

  onTapDown: (TapDownDetails tapDownDetails) {
    // Write the actions here
  }

 

Using onTapUp

onTapUp is triggered when a pointer has stopped to contact the screen at a particular location, just before onTap (if tap gesture wins) or onTapCancel (if tap gesture doesn't win). It has a parameter of type TapUpDetails.

  onTapUp: (TapUpDetails tapUpDetails) {
    // Write the actions here
  }

 

Using onTap

onTap is triggered when a tap gesture has occured and wins.

  onTap: () {
    // Write the actions here
  }

 

Using onTapCancel

onTapCancel is triggered when a pointer that caused onTapDown doesn't end up causing a complete tap. For example, if the pointer has been moved outside the tap area when it's released.

  onTapCancel: () {
    // Write the actions here
  }

 

Using onSecondaryTap

onSecondaryTap is triggered when a tap with secondary button has occured and wins.

  onSecondaryTap: () {
    // Write the actions here
  }

 

Using onSecondaryTapDown

onSecondaryTapDown is triggered when a pointer with a secondary button has started to contact the screen at a particular location. It doesn't wait until the tap gesture wins. It has a parameter of type TapDownDetails.

  onSecondaryTapDown: (TapDownDetails tapDownDetails) {
    // Write the actions here
  }

 

Using onSecondaryTapUp

onSecondaryTapUp is triggered when a pointer with a secondary button has stopped to contact the screen at a particular location, just before onSecondaryTap (if tap gesture wins) or onSecondaryTapCancel (if tap gesture doesn't win). It has a parameter of type TapUpDetails.

  onSecondaryTapUp: (TapUpDetails tapUpDetails) {
    // Write the actions here
  }

 

Using onSecondaryTapCancel

onSecondaryTapCancel is triggered when a pointer that caused onSecondaryTapDown doesn't end up causing a complete tap. For example, if the pointer has been moved outside the tap area when it's released.

  onSecondaryTapCancel: () {
    // Write the actions here
  }

 

Using onDoubleTap

onDoubleTap is triggered when the user does two quick taps in succession at the same location.

  onDoubleTap: () {
    // Write the actions here
  }

 

Using onLongPress

onLongPress is triggered when a pointer of a primary button has remained in contact at a particular location for a long period.

  onLongPress: () {
    // Write the actions here
  }

 

Using onLongPressStart

onLongPressStart is triggered when a pointer of a primary button has remained in contact at a particular location for a long period. It has a parameter of type LongPressStartDetails.

  onLongPressStart: (LongPressStartDetails longPressStartDetails) {
    // Write the actions here
  }

 

Using onLongPressMoveUpdate

onLongPressMoveUpdate is triggered when a pointer has been moved after a long press with a primary button. It has a parameter of type LongPressMoveUpdateDetails.

  onLongPressMoveUpdate: (LongPressMoveUpdateDetails longPressMoveUpdateDetails) {
    // Write the actions here
  }

 

Using onLongPressUp

onLongPressUp is triggered when a pointer of a primary button has stopped to contact the screen at a particular location after a long press.

  onLongPressUp: () {
    // Write the actions here
  }

 

Using onLongPressEnd

onLongPressEnd is triggered when a pointer of a primary button has stopped to contact the screen at a particular location after a long press. It has a parameter of type LongPressEndDetails.

  onLongPressEnd: (LongPressEndDetails longPressEndDetails) {
    // Write the actions here
  }

 

Using onSecondaryLongPress

onSecondaryLongPress is triggered when a pointer of a secondary button has remained in contact at a particular location for a long period.

  onSecondaryLongPress: () {
    // Write the actions here
  }

 

Using onSecondaryLongPressStart

onSecondaryLongPressStart is triggered when a pointer of a secondary button has remained in contact at a particular location for a long period. It has a parameter of type LongPressStartDetails.

  onSecondaryLongPressStart: (LongPressStartDetails longPressStartDetails) {
    // Write the actions here
  }

 

Using onSecondaryLongPressMoveUpdate

onSecondaryLongPressMoveUpdate is triggered when a pointer has been moved after a long press with a secondary button. It has a parameter of type LongPressMoveUpdateDetails.

  onSecondaryLongPressMoveUpdate: (LongPressMoveUpdateDetails longPressMoveUpdateDetails) {
    // Write the actions here
  }

 

Using onSecondaryLongPressUp

onSecondaryLongPressUp is triggered when a pointer of a secondary button has stopped to contact the screen at a particular location after a long press.

  onSecondaryLongPressUp: () {
    // Write the actions here
  }

 

Using onSecondaryLongPressEnd

onSecondaryLongPressEnd is triggered when a pointer of a secondary button has stopped to contact the screen at a particular location after a long press.

  onSecondaryLongPressEnd: () {
    // Write the actions here
  }

 

Using onVerticalDragDown

onVerticalDragDown is triggered when a pointer of a primary button has contacted the screen and might begin to move vertically. It has a parameter of type DragDownDetails.

  onVerticalDragDown: (DragDownDetails dragDownDetails) {
    // Write the actions here
  }

 

Using onVerticalDragStart

onVerticalDragStart is triggered when a pointer of a primary button has contacted the screen and has begun to move vertically. It has a parameter of type DragStartDetails.

  onVerticalDragStart: (DragStartDetails dragStartDetails) {
    // Write the actions here
  }

 

Using onVerticalDragUpdate

onVerticalDragUpdate is triggered when a pointer of a primary button has contacted the screen and is moving veritcally. It has a parameter of type DragUpdateDetails.

  onVerticalDragUpdate: (DragUpdateDetails dragUpdateDetails) {
    // Write the actions here
  }

 

Using onVerticalDragEnd

onVerticalDragEnd is triggered when a pointer of a primary button that was moving vertically has stopped to contact the screen at a specific velocity. It has a parameter of type DragEndDetails.

  onVerticalDragEnd: (DragEndDetails dragEndDetails) {
    // Write the actions here
  }

 

Using onVerticalDragCancel

onVerticalDragCancel is triggered when a pointer that had triggered onVerticalDragDown doesn't complete.

  onVerticalDragCancel: () {
    // Write the actions here
  }

 

Using onHorizontalDragDown

onHorizontalDragDown is triggered when a pointer of a primary button has contacted the screen and might begin to move horizontally. It has a parameter of type DragDownDetails.

  onHorizontalDragDown: (DragDownDetails dragDownDetails) {
    // Write the actions here
  }

 

Using onHorizontalDragStart

onHorizontalDragStart is triggered when a pointer of a primary button has contacted the screen and has begun to move horizontally. It has a parameter of type DragStartDetails.

  onHorizontalDragStart: (DragStartDetails dragStartDetails) {
    // Write the actions here
  }

 

Using onHorizontalDragUpdate

onHorizontalDragUpdate is triggered when a pointer of a primary button has contacted the screen and is moving horizontally. It has a parameter of type DragUpdateDetails.

  onHorizontalDragUpdate: (DragUpdateDetails dragUpdateDetails) {
    // Write the actions here
  }

 

Using onHorizontalDragEnd

onHorizontalDragEnd is triggered when a pointer of a primary button that was moving vertically has stopped to contact the screen at a specific velocity. It has a parameter of type DragEndDetails.

  onHorizontalDragEnd: (DragEndDetails dragEndDetails) {
    // Write the actions here
  }

 

Using onHorizontalDragCancel

onHorizontalDragCancel is triggered when a pointer that had triggered onHorizontalDragDown doesn't complete.

  onHorizontalDragCancel: () {
    // Write the actions here
  }

 

Using onForcePressStart

onForcePressStart is triggered when a pointer has pressed with sufficient force to initiate a force press with an amount of at least ForcePressGestureRecognizer.startPressure. It has a parameter of type ForcePressDetails.

  onForcePressStart: (ForcePressDetails forcePressDetails) {
    // Write the actions here
  }

 

Using onForcePressPeak

onForcePressPeak is triggered when a pointer has pressed with the maximum force with an amount of at least ForcePressGestureRecognizer.startPressure. It has a parameter of type ForcePressDetails.

  onForcePressPeak: (ForcePressDetails forcePressDetails) {
    // Write the actions here
  }

 

Using onForcePressUpdate

onForcePressUpdate is triggered when a pointer has passed ForcePressGestureRecognizer.startPressure and is moving on the screen. It has a parameter of type ForcePressDetails.

  onForcePressUpdate: (ForcePressDetails forcePressDetails) {
    // Write the actions here
  }

 

Using onForcePressEnd

onForcePressUpdate is triggered when a pointer had passed ForcePressGestureRecognizer.startPressure and no longer in contact with the screen. It has a parameter of type ForcePressDetails.

  onForcePressEnd: (ForcePressDetails forcePressDetails) {
    // Write the actions here
  }

 

Using onPanDown

onPanDown is triggered when a pointer has contacted the screen with a primary button and might begin to move. It has a parameter of type DragDownDetails.

  onPanDown: (DragDownDetails dragDownDetails) {
    // Write the actions here
  }

 

Using onPanStart

onPanStart is triggered when a pointer has contacted the screen with a primary button and has begun to move. It has a parameter of type DragStartDetails.

  onPanStart: (DragStartDetails dragStartDetails) {
    // Write the actions here
  }

 

Using onPanUpdate

onPanUpdate is triggered when a pointer has contacted the screen with a primary button and is moving. It has a parameter of type DragUpdateDetails.

  onPanUpdate: (DragUpdateDetails dragUpdateDetails) {
    // Write the actions here
  }

 

Using onPanEnd

onPanEnd is triggered when a pointer of a primary button that was moving has stopped to contact the screen at a specific velocity. It has a parameter of type DragEndDetails.

  onTap: (DragEndDetails dragEndDetails) {
    // Write the actions here
  }

 

Using onPanCancel

onPanCancel is triggered when a pointer that had triggered onPanDown doesn't complete.

  onPanCancel: () {
    // Write the actions here
  }

 

Using onScaleStart

onScaleStart is triggered when a pointer has established a focal point and initial scale of 1.0. It has a parameter of type ScaleStartDetails.

  onScaleStart: (ScaleStartDetails scaleStartDetails) {
    // Write the actions here
  }

 

Using onScaleUpdate

onScaleUpdate is triggered when a pointer has a new focal point. It has a parameter of type ScaleUpdateDetails.

  onScaleUpdate: (ScaleUpdateDetails scaleUpdateDetails) {
    // Write the actions here
  }

 

Using onScaleEnd

onScaleEnd is triggered when a pointer has a new focal point. It has a parameter of type ScaleEndDetails.

  onScaleEnd: (ScaleEndDetails scaleEndDetails) {
    // Write the actions here
  }

 

Gesture Detail Classes

On the previous section, you can see that there are some callback function that accepts a parameter that allows you to get a more detailed information. Some of them have parameter of the same type. Below are the properties of the classes used as parameter.

TapDownDetails

  • Offset globalPosition: The global position at which the pointer contacted the screen.
  • PointerDeviceKind kind: The kind of the device that initiated the event.
  • Offset localPosition: The local position at which the pointer contacted the screen.

 

TapUpDetails

  • Offset globalPosition: The global position at which the pointer contacted the screen.
  • Offset localPosition: The local position at which the pointer contacted the screen.

 

LongPressStartDetails

  • Offset globalPosition: The global position at which the pointer contacted the screen.
  • Offset localPosition: The local position at which the pointer contacted the screen.

 

LongPressMoveUpdateDetails

  • Offset globalPosition: The global position at which the pointer contacted the screen.
  • Offset localPosition: The local position at which the pointer contacted the screen.
  • Offset offsetFromOrigin: A delta offset from the point where the long press drag initially contacted the screen to the point where the pointer is currently located.
  • Offset localOffsetFromOrigin: A local delta offset from the point where the long press drag initially contacted the screen to the point where the pointer is currently located.

 

LongPressEndDetails

  • Offset globalPosition: The global position at which the pointer contacted the screen.
  • Offset localPosition: The local position at which the pointer contacted the screen.
  • Velocity velocity: The pointer's velocity when it stopped contacting the screen.

 

DragDownDetails

  • Offset globalPosition: The global position at which the pointer contacted the screen.
  • Offset localPosition: The local position in the coordinate system of the event receiver at which the pointer contacted the screen.

 

DragStartDetails

  • Offset globalPosition: The global position at which the pointer contacted the screen.
  • Offset localPosition: The local position in the coordinate system of the event receiver at which the pointer contacted the screen.
  • Duration sourceTimeStamp: Recorded timestamp of the source pointer event that triggered the drag event.

 

DragUpdateDetails

  • Duration sourceTimeStamp: Recorded timestamp of the source pointer event that triggered the drag event..
  • Offset delta: The amount the pointer has moved in the coordinate space of the event receiver since the previous update..
  • double primaryDelta: The amount the pointer has moved along the primary axis in the coordinate space of the event receiver since the previous update..
  • Offset globalPosition: The pointer's global position when it triggered this update.
  • Offset localPosition: The local position in the coordinate system of the event receiver at which the pointer contacted the screen.

 

DragEndDetails

  • Velocity velocity: The velocity the pointer was moving when it stopped contacting the screen.
  • double primaryVelocity: The velocity the pointer was moving along the primary axis when it stopped contacting the screen, in logical pixels per second.

 

ScaleStartDetails

  • Offset focalPoint: The initial focal point of the pointers in contact with the screen.
  • Offset localFocalPoint: The initial focal point of the pointers in contact with the screen.

 

ScaleUpdateDetails

  • Offset focalPoint: The focal point of the pointers in contact with the screen.
  • Offset localFocalPoint: The focal point of the pointers in contact with the screen.
  • double scale: The scale implied by the average distance between the pointers in contact with the screen.
  • double horizontalScale: The scale implied by the average distance along the horizontal axis between the pointers in contact with the screen.
  • double verticalScale: The scale implied by the average distance along the vertical axis between the pointers in contact with the screen.
  • double rotation: The angle implied by the first two pointers to enter in contact with the screen.

 

ScaleEndDetails

  • Velocity velocity: The velocity of the last pointer to be lifted off of the screen.

 

ForcePressDetails

  • Offset globalPosition: The global position at which the function was called.
  • Offset localPosition: The local position at which the function was called.
  • double pressure: The pressure of the pointer on the screen.

 

GestureDetector Properties

Below are the properties of GestureDetector excluding the properties for handling specific gesture types as they're already explained above.

  • Key key: The widget's key, used to control if it should be replaced.
  • Widget child: The widget below this widget in the tree.
  • HitTestBehavior behavior: How this gesture detector should behave during hit testing.
  • bool excludeFromSemantics: Whether to exclude these gestures from the semantics tree.
  • DragStartBehavior dragStartBehavior: Determines the way that drag start behavior is handled. Defaults to DragStartBehavior.start.

 

Full Code

Here's the full code example that uses GestureDetector for detecting tap and long press.

  import 'package:flutter/material.dart';
  
  void main() => runApp(MyApp());
  
  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Woolha.com Flutter Tutorial',
        home: _GestureDetectorExample(),
      );
    }
  }
  
  class _GestureDetectorExample extends StatelessWidget {
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Woolha.com Flutter Tutorial'),
        ),
        body: Center(
          child: GestureDetector(
            onTap: () {
              print('onTap');
              Feedback.forTap(context);
            },
            onLongPress: () {
              print('onLongPress');
              Feedback.forLongPress(context);
            },
            child: RaisedButton(
              child: Text('Click'),
            ),
          ),
        ),
      );
    }
  }