SerialTapGestureRecognizer class Null safety

Recognizes serial taps (taps in a series).

A collection of taps are considered to be in a series if they occur in rapid succession in the same location (within a tolerance). The number of taps in the series is its count. A double-tap, for instance, is a special case of a tap series with a count of two.

Gesture arena behavior

SerialTapGestureRecognizer competes on all pointer events (regardless of button). It will declare defeat if it determines that a gesture is not a tap (e.g. if the pointer is dragged too far while it's contacting the screen). It will immediately declare victory for every tap that it recognizes.

Each time a pointer contacts the screen, this recognizer will enter that gesture into the arena. This means that this recognizer will yield multiple winning entries in the arena for a single tap series as the series progresses.

If this recognizer loses the arena (either by declaring defeat or by another recognizer declaring victory) while the pointer is contacting the screen, it will fire onSerialTapCancel, and onSerialTapUp will not be fired.

Button behavior

A tap series is defined to have the same buttons across all taps. If a tap with a different combination of buttons is delivered in the middle of a series, it will "steal" the series and begin a new series, starting the count over.

Interleaving tap behavior

A tap must be completed in order for a subsequent tap to be considered "in the same series" as that tap. Thus, if tap A is in-progress (the down event has been received, but the corresponding up event has not yet been received), and tap B begins (another pointer contacts the screen), tap A will fire onSerialTapCancel, and tap B will begin a new series (tap B's SerialTapDownDetails.count will be 1).

Relation to TapGestureRecognizer and DoubleTapGestureRecognizer

SerialTapGestureRecognizer fires onSerialTapDown and onSerialTapUp for every tap that it recognizes (passing the count in the details), regardless of whether that tap is a single-tap, double-tap, etc. This makes it especially useful when you want to respond to every tap in a series. Contrast this with DoubleTapGestureRecognizer, which only fires if the user completes a double-tap, and TapGestureRecognizer, which doesn't fire if the recognizer is competing with a DoubleTapGestureRecognizer, and the user double-taps.

For example, consider a list item that should be selected on the first tap and cause an edit dialog to open on a double-tap. If you use both TapGestureRecognizer and DoubleTapGestureRecognizer, there are a few problems:

  1. If the user single-taps the list item, it will not select the list item until after enough time has passed to rule out a double-tap.
  2. If the user double-taps the list item, it will not select the list item at all.

The solution is to use SerialTapGestureRecognizer and use the tap count to either select the list item or open the edit dialog.

When competing with TapGestureRecognizer and DoubleTapGestureRecognizer

Unlike TapGestureRecognizer and DoubleTapGestureRecognizer, SerialTapGestureRecognizer aggressively declares victory when it detects a tap, so when it is competing with those gesture recognizers, it will beat them in the arena, regardless of which recognizer entered the arena first.



SerialTapGestureRecognizer({Object? debugOwner, Set<PointerDeviceKind>? supportedDevices})
Creates a serial tap gesture recognizer.


debugDescription String
Returns a very short pretty description of the gesture that the recognizer looks for, like 'tap' or 'horizontal drag'.
read-only, override
debugOwner Object?
The recognizer's owner. [...]
final, inherited
gestureSettings DeviceGestureSettings?
Optional device specific configuration for device gestures that will take precedence over framework defaults.
read / write, inherited
hashCode int
The hash code for this object. [...]
read-only, inherited
isTrackingPointer bool
Indicates whether this recognizer is currently tracking a pointer that's in contact with the screen. [...]
onSerialTapCancel GestureSerialTapCancelCallback?
A pointer that previously triggered onSerialTapDown will not end up triggering the corresponding onSerialTapUp. [...]
read / write
onSerialTapDown GestureSerialTapDownCallback?
A pointer has contacted the screen at a particular location, which might be the start of a serial tap. [...]
read / write
onSerialTapUp GestureSerialTapUpCallback?
A pointer has stopped contacting the screen at a particular location, representing a serial tap. [...]
read / write
runtimeType Type
A representation of the runtime type of the object.
read-only, inherited


acceptGesture(int pointer) → void
Called when this member wins the arena for the given pointer id.
addAllowedPointer(PointerDownEvent event) → void
Registers a new pointer that's been checked to be allowed by this gesture recognizer. [...]
addPointer(PointerDownEvent event) → void
Registers a new pointer that might be relevant to this gesture detector. [...]
debugDescribeChildren() List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children. [...]
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node. [...]
dispose() → void
Releases any resources used by the object. [...]
getKindForPointer(int pointer) PointerDeviceKind
For a given pointer ID, returns the device kind associated with it. [...]
@protected, inherited
handleNonAllowedPointer(PointerDownEvent event) → void
Handles a pointer being added that's not allowed by this recognizer. [...]
@protected, inherited
invokeCallback<T>(String name, RecognizerCallback<T> callback, {String debugReport()?}) → T?
Invoke a callback provided by the application, catching and logging any exceptions. [...]
@protected, inherited
isPointerAllowed(PointerDownEvent event) bool
Checks whether or not a pointer is allowed to be tracked by this recognizer.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a non-existent method or property is accessed. [...]
rejectGesture(int pointer) → void
Called when this member loses the arena for the given pointer id.
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep. [...]
toString({DiagnosticLevel minLevel =}) String
A string representation of this object. [...]
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a string representation of this node and its descendants. [...]
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a one-line detailed description of the object. [...]
toStringShort() String
A brief description of this object, usually just the runtimeType and the hashCode. [...]


operator ==(Object other) bool
The equality operator. [...]