Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dipendra-sharma/0d5182638a0a083419b7158950ed4f49 to your computer and use it in GitHub Desktop.
Save dipendra-sharma/0d5182638a0a083419b7158950ed4f49 to your computer and use it in GitHub Desktop.
Advanced multi touch gesture detection in flutter
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'multi_drag_gestures.dart';
typedef GestureMultiDragUpdateCallback = void Function(
Offset initialPosition, Offset latestPosition, double delta);
typedef GestureMultiDragEndCallback = void Function(
Offset initialPosition, Offset latestPosition, double delta);
typedef GestureMultiDragCancelCallback = void Function();
/// This is an advanced version of normal Gesture detector.
///
/// This detector includes MultiDrag Gestures along with most of the
/// normal gestures supported by [GestureDetector] widget.
///
/// Author Harshvardhan Joshi
class CustomGestureDetector extends StatefulWidget {
/// The widget which needs to access the gestures
final Widget child;
/// This is the number of pointers which is required to
/// at least consider a gesture
///
/// It can range from minimum 1 to max pointers supported by the [MultiDragGestureRecognizer]
///
/// If the value is set to 2, then the the gesture recognizer
/// will handle simple touch gestures (requiring only one pointer) and
/// multi touch gestures (requiring more than one pointers).
///
final int supportedPointerCount;
/// A [HitTestBehavior] value is used to define how the user's touch
/// event should be handled on detection.
final HitTestBehavior behaviour;
/// A [DragStartBehavior] value is used to define if the initial value
/// of a drag gesture will be user's first touch or the position when drag
/// event actually starts/detected.
final DragStartBehavior dragStartBehavior;
/// A callback for simple horizontal drag start gesture
final GestureDragStartCallback onHorizontalDragStart;
/// A callback for simple horizontal drag update gesture
final GestureDragUpdateCallback onHorizontalDragUpdate;
/// A callback for simple horizontal drag end gesture
final GestureDragEndCallback onHorizontalDragEnd;
/// A callback for simple horizontal drag cancel gesture
final GestureDragCancelCallback onHorizontalDragCancel;
/// A callback for simple vertical drag start gesture
final GestureDragStartCallback onVerticalDragStart;
/// A callback for simple vertical drag update gesture
final GestureDragUpdateCallback onVerticalDragUpdate;
/// A callback for simple vertical drag end gesture
final GestureDragEndCallback onVerticalDragEnd;
/// A callback for simple vertical drag cancel gesture
final GestureDragCancelCallback onVerticalDragCancel;
/// A callback for multi touch horizontal drag start gesture
final GestureMultiDragStartCallback onMultiHorizontalDragStart;
/// A callback for multi touch horizontal drag update gesture
final GestureMultiDragUpdateCallback onMultiHorizontalDragUpdate;
/// A callback for multi touch horizontal drag end gesture
final GestureMultiDragEndCallback onMultiHorizontalDragEnd;
/// A callback for multi touch horizontal drag cancel gesture
final GestureMultiDragCancelCallback onMultiHorizontalDragCancel;
/// A callback for multi touch vertical drag start gesture
final GestureMultiDragStartCallback onMultiVerticalDragStart;
/// A callback for multi touch vertical drag update gesture
final GestureMultiDragUpdateCallback onMultiVerticalDragUpdate;
/// A callback for multi touch vertical drag end gesture
final GestureMultiDragEndCallback onMultiVerticalDragEnd;
/// A callback for multi touch vertical drag cancel gesture
final GestureMultiDragCancelCallback onMultiVerticalDragCancel;
/// A callback for simple PAN start gesture
final GestureDragStartCallback onPanStart;
/// A callback for simple PAN update gesture
final GestureDragUpdateCallback onPanUpdate;
/// A callback for simple PAN end gesture
final GestureDragEndCallback onPanEnd;
/// A callback for simple PAN cancel gesture
final GestureDragCancelCallback onPanCancel;
/// A callback for simple scale start gesture
final GestureScaleStartCallback onScaleStart;
/// A callback for simple scale update gesture
final GestureScaleUpdateCallback onScaleUpdate;
/// A callback for simple scale end gesture
final GestureScaleEndCallback onScaleEnd;
/// A callback for a double tap gesture
final GestureTapCallback onDoubleTap;
/// A callback for a long press gesture
final GestureLongPressCallback onLongPress;
/// Public constructor
const CustomGestureDetector({
Key key,
this.supportedPointerCount = 1,
this.child,
this.behaviour,
this.onDoubleTap,
this.onLongPress,
this.onMultiHorizontalDragStart,
this.onMultiHorizontalDragUpdate,
this.onMultiHorizontalDragEnd,
this.onHorizontalDragStart,
this.onHorizontalDragUpdate,
this.onHorizontalDragEnd,
this.onHorizontalDragCancel,
this.onVerticalDragStart,
this.onVerticalDragUpdate,
this.onVerticalDragEnd,
this.onVerticalDragCancel,
this.onMultiHorizontalDragCancel,
this.onMultiVerticalDragStart,
this.onMultiVerticalDragUpdate,
this.onMultiVerticalDragEnd,
this.onMultiVerticalDragCancel,
this.onPanStart,
this.onPanUpdate,
this.onPanEnd,
this.onPanCancel,
this.onScaleStart,
this.onScaleUpdate,
this.onScaleEnd,
this.dragStartBehavior = DragStartBehavior.start,
}) : assert(child != null),
assert(supportedPointerCount != null && supportedPointerCount > 0),
super(key: key);
@override
_CustomGestureDetectorState createState() => _CustomGestureDetectorState();
}
class _CustomGestureDetectorState extends State<CustomGestureDetector> {
int get supportedPointerCount => widget.supportedPointerCount;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
final Map<Type, GestureRecognizerFactory> _gestures =
<Type, GestureRecognizerFactory>{};
_addDoubleTapGesture(_gestures, widget.onDoubleTap);
_addLongPressGesture(_gestures, widget.onLongPress);
_addPanGesture(
_gestures,
widget.onPanStart,
widget.onPanUpdate,
widget.onPanEnd,
widget.onPanCancel,
widget.dragStartBehavior,
);
_addScaleGesture(_gestures, widget.onScaleStart, widget.onScaleUpdate,
widget.onScaleEnd, widget.dragStartBehavior);
if (supportedPointerCount > 1) {
_addMultiHorizontalDragGesture(
_gestures,
widget.onMultiHorizontalDragStart,
widget.onMultiHorizontalDragUpdate,
widget.onMultiHorizontalDragEnd,
widget.onMultiHorizontalDragCancel,
widget.onHorizontalDragStart,
widget.onHorizontalDragUpdate,
widget.onHorizontalDragEnd,
widget.onHorizontalDragCancel,
);
_addMultiVerticalDragGesture(
_gestures,
widget.onMultiVerticalDragStart,
widget.onMultiVerticalDragUpdate,
widget.onMultiVerticalDragEnd,
widget.onMultiVerticalDragCancel,
widget.onVerticalDragStart,
widget.onVerticalDragUpdate,
widget.onVerticalDragEnd,
widget.onVerticalDragCancel,
);
} else {
_addVerticalDragGesture(
_gestures,
widget.onVerticalDragStart,
widget.onVerticalDragUpdate,
widget.onVerticalDragEnd,
widget.onVerticalDragCancel,
widget.dragStartBehavior,
);
_addHorizontalDragGesture(
_gestures,
widget.onHorizontalDragStart,
widget.onHorizontalDragUpdate,
widget.onHorizontalDragEnd,
widget.onHorizontalDragCancel,
widget.dragStartBehavior);
}
return RawGestureDetector(
behavior: widget.behaviour,
gestures: _gestures,
child: widget.child,
);
}
void _addDoubleTapGesture(
Map<Type, GestureRecognizerFactory<GestureRecognizer>> gestures,
GestureTapCallback onDoubleTap) {
if (onDoubleTap != null) {
gestures[DoubleTapGestureRecognizer] =
GestureRecognizerFactoryWithHandlers<DoubleTapGestureRecognizer>(
() => DoubleTapGestureRecognizer(debugOwner: this),
(DoubleTapGestureRecognizer instance) {
instance..onDoubleTap = onDoubleTap;
},
);
}
}
void _addLongPressGesture(
Map<Type, GestureRecognizerFactory<GestureRecognizer>> gestures,
GestureLongPressCallback onLongPress) {
if (onLongPress != null) {
gestures[LongPressGestureRecognizer] =
GestureRecognizerFactoryWithHandlers<LongPressGestureRecognizer>(
() => LongPressGestureRecognizer(debugOwner: this),
(LongPressGestureRecognizer instance) {
instance..onLongPress = onLongPress;
},
);
}
}
void _addVerticalDragGesture(
Map<Type, GestureRecognizerFactory<GestureRecognizer>> gestures,
GestureDragStartCallback onVerticalDragStart,
GestureDragUpdateCallback onVerticalDragUpdate,
GestureDragEndCallback onVerticalDragEnd,
GestureDragCancelCallback onVerticalDragCancel,
DragStartBehavior dragStartBehavior) {
if (onVerticalDragStart != null ||
onVerticalDragUpdate != null ||
onVerticalDragEnd != null ||
onVerticalDragCancel != null) {
gestures[VerticalDragGestureRecognizer] =
GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer(debugOwner: this),
(VerticalDragGestureRecognizer instance) {
instance
..onStart = onVerticalDragStart
..onUpdate = onVerticalDragUpdate
..onEnd = onVerticalDragEnd
..onCancel = onVerticalDragCancel
..dragStartBehavior = dragStartBehavior;
},
);
}
}
void _addHorizontalDragGesture(
Map<Type, GestureRecognizerFactory<GestureRecognizer>> gestures,
GestureDragStartCallback onHorizontalDragStart,
GestureDragUpdateCallback onHorizontalDragUpdate,
GestureDragEndCallback onHorizontalDragEnd,
GestureDragCancelCallback onHorizontalDragCancel,
DragStartBehavior dragStartBehavior) {
if (onHorizontalDragStart != null ||
onHorizontalDragUpdate != null ||
onHorizontalDragEnd != null ||
onHorizontalDragCancel != null) {
gestures[HorizontalDragGestureRecognizer] =
GestureRecognizerFactoryWithHandlers<HorizontalDragGestureRecognizer>(
() => HorizontalDragGestureRecognizer(debugOwner: this),
(HorizontalDragGestureRecognizer instance) {
instance
..onStart = onHorizontalDragStart
..onUpdate = onHorizontalDragUpdate
..onEnd = onHorizontalDragEnd
..onCancel = onHorizontalDragCancel
..dragStartBehavior = dragStartBehavior;
},
);
}
}
void _addPanGesture(
Map<Type, GestureRecognizerFactory<GestureRecognizer>> gestures,
GestureDragStartCallback onPanStart,
GestureDragUpdateCallback onPanUpdate,
GestureDragEndCallback onPanEnd,
GestureDragCancelCallback onPanCancel,
DragStartBehavior dragStartBehavior) {
if (onPanStart != null ||
onPanUpdate != null ||
onPanEnd != null ||
onPanCancel != null) {
gestures[PanGestureRecognizer] =
GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
() => PanGestureRecognizer(debugOwner: this),
(PanGestureRecognizer instance) {
instance
..onStart = onPanStart
..onUpdate = onPanUpdate
..onEnd = onPanEnd
..onCancel = onPanCancel
..dragStartBehavior = dragStartBehavior;
},
);
}
}
void _addScaleGesture(
Map<Type, GestureRecognizerFactory<GestureRecognizer>> gestures,
GestureScaleStartCallback onScaleStart,
GestureScaleUpdateCallback onScaleUpdate,
GestureScaleEndCallback onScaleEnd,
DragStartBehavior dragStartBehavior) {
if (onScaleStart != null || onScaleUpdate != null || onScaleEnd != null) {
gestures[ScaleGestureRecognizer] =
GestureRecognizerFactoryWithHandlers<ScaleGestureRecognizer>(
() => ScaleGestureRecognizer(debugOwner: this),
(ScaleGestureRecognizer instance) {
instance
..onStart = onScaleStart
..onUpdate = onScaleUpdate
..onEnd = onScaleEnd;
},
);
}
}
void _addMultiHorizontalDragGesture(
Map<Type, GestureRecognizerFactory<GestureRecognizer>> gestures,
GestureMultiDragStartCallback onMultiHorizontalDragStart,
GestureMultiDragUpdateCallback onMultiHorizontalDragUpdate,
GestureMultiDragEndCallback onMultiHorizontalDragEnd,
GestureMultiDragCancelCallback onMultiHorizontalDragCancel,
GestureDragStartCallback onHorizontalDragStart,
GestureDragUpdateCallback onHorizontalDragUpdate,
GestureDragEndCallback onHorizontalDragEnd,
GestureDragCancelCallback onHorizontalDragCancel,
) {
if (onMultiHorizontalDragStart != null ||
onMultiHorizontalDragUpdate != null ||
onHorizontalDragStart != null ||
onHorizontalDragUpdate != null) {
gestures[CustomHorizontalMultiDragRecognizer] =
getMultiHorizontalDragGestureRecognizer(
this,
onMultiHorizontalDragStart: onMultiHorizontalDragStart,
onMultiHorizontalDragUpdate: onMultiHorizontalDragUpdate,
onMultiHorizontalDragEnd: onMultiHorizontalDragEnd,
onMultiHorizontalDragCancel: onMultiHorizontalDragCancel,
onHorizontalDragStart: onHorizontalDragStart,
onHorizontalDragUpdate: onHorizontalDragUpdate,
onHorizontalDragEnd: onHorizontalDragEnd,
onHorizontalDragCancel: onHorizontalDragCancel,
supportedPointerCount: supportedPointerCount,
);
}
}
void _addMultiVerticalDragGesture(
Map<Type, GestureRecognizerFactory<GestureRecognizer>> gestures,
GestureMultiDragStartCallback onMultiVerticalDragStart,
GestureMultiDragUpdateCallback onMultiVerticalDragUpdate,
GestureMultiDragEndCallback onMultiVerticalDragEnd,
GestureMultiDragCancelCallback onMultiVerticalDragCancel,
GestureDragStartCallback onVerticalDragStart,
GestureDragUpdateCallback onVerticalDragUpdate,
GestureDragEndCallback onVerticalDragEnd,
GestureDragCancelCallback onVerticalDragCancel,
) {
if (onMultiVerticalDragStart != null ||
onMultiVerticalDragUpdate != null ||
onVerticalDragStart != null ||
onVerticalDragEnd != null) {
gestures[CustomVerticalMultiDragRecognizer] =
getMultiVerticalDragGestureRecognizer(
this,
supportedPointerCount: supportedPointerCount,
onMultiVerticalDragStart: onMultiVerticalDragStart,
onMultiVerticalDragUpdate: onMultiVerticalDragUpdate,
onMultiVerticalDragEnd: onMultiVerticalDragEnd,
onMultiVerticalDragCancel: onMultiVerticalDragCancel,
onVerticalDragStart: onVerticalDragStart,
onVerticalDragUpdate: onVerticalDragUpdate,
onVerticalDragEnd: onVerticalDragEnd,
onVerticalDragCancel: onVerticalDragCancel,
);
}
}
}
import 'dart:async';
import 'package:flutter/material.dart';
/// This class handles a [delayedProcess] with a given [waitDuration]
class DelayedProcessHandler {
Timer _waitingTimer;
final Duration _defaultDuration = Duration(seconds: 10);
/// This holds the process which should be executed after the provided delay
Function delayedProcess;
/// This value is used as a waiting duration, after this duration the process
/// will be executed.
Duration waitDuration;
///Public Constructor
DelayedProcessHandler({@required this.delayedProcess, this.waitDuration})
: assert(delayedProcess != null);
/// This method will start the waiting process
void startWaiting() {
waitDuration ??= _defaultDuration;
// to cancel previous waiting task assigned to this handler
stopWaiting();
_waitingTimer = Timer(waitDuration, () {
// AppLog.debug(LogOwner.hjoshi,
// 'DelayedProcessHandler.startWaiting() : triggering process...');
delayedProcess();
});
}
/// This method will stop the waiting process
void stopWaiting() {
_waitingTimer?.cancel();
_waitingTimer = null;
}
}
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_investar/src/utils/delayed_process_handler.dart';
import 'custom_gesture_detector.dart';
/// Class for recognizing multi touch vertical gestures
class CustomVerticalMultiDragRecognizer
extends VerticalMultiDragGestureRecognizer {
/// Amount of current simultaneous pointers/touches
int _pointerCount;
/// Amount of minimum required simultaneous pointers/touches
final int supportedPointerCount;
/// A delayed process handler to execute single touch alternative
/// of a gesture if multi touch gesture's minimum was not recognized properly
/// within a limited amount of time
DelayedProcessHandler _delayedProcessHandler;
/// Multi touch vertical drag start
final GestureMultiDragStartCallback onMultiVerticalDragStart;
/// Multi touch vertical drag update
final GestureMultiDragUpdateCallback onMultiVerticalDragUpdate;
/// Multi touch vertical drag end
final GestureMultiDragEndCallback onMultiVerticalDragEnd;
/// Multi touch vertical drag cancel
final GestureMultiDragCancelCallback onMultiVerticalDragCancel;
/// Single touch vertical drag start
final GestureDragStartCallback onVerticalDragStart;
/// Single touch vertical drag update
final GestureDragUpdateCallback onVerticalDragUpdate;
/// Single touch vertical drag end
final GestureDragEndCallback onVerticalDragEnd;
/// Single touch vertical drag cancel
final GestureDragCancelCallback onVerticalDragCancel;
/// Public constructor
CustomVerticalMultiDragRecognizer(
Object debugOwner,
this.supportedPointerCount,
this.onMultiVerticalDragStart,
this.onMultiVerticalDragUpdate,
this.onMultiVerticalDragEnd,
this.onMultiVerticalDragCancel,
this.onVerticalDragStart,
this.onVerticalDragUpdate,
this.onVerticalDragEnd,
this.onVerticalDragCancel)
: assert(onMultiVerticalDragStart != null ||
onMultiVerticalDragUpdate != null),
super(debugOwner: debugOwner) {
_delayedProcessHandler ??= DelayedProcessHandler(
delayedProcess: confirmAdditionalPointers,
waitDuration: Duration(milliseconds: 100));
onStart = _handleMultiDragOnStart;
}
Drag _handleMultiDragOnStart(Offset position) {
if (_pointerCount < supportedPointerCount) {
_pointerCount++;
_delayedProcessHandler.startWaiting();
}
return ItemDrag(_onDragUpdate, _onDragEnd, _onCancel);
}
void _onDragUpdate(
Offset initialPosition,
Offset latestPosition,
double delta,
) {
if (_pointerCount == 1) {
if (onVerticalDragUpdate == null) {
return;
}
onVerticalDragUpdate(DragUpdateDetails(
globalPosition: latestPosition,
delta: Offset(0.0, delta),
primaryDelta: delta));
} else {
onMultiVerticalDragUpdate(initialPosition, latestPosition, delta);
}
}
void _onDragEnd(
Offset initialPosition,
Offset latestPosition,
double delta,
) {
if (_pointerCount == 1) {
if (onVerticalDragEnd == null) {
return;
}
onVerticalDragEnd(DragEndDetails(
velocity: Velocity(
pixelsPerSecond:
fromDifference(initialPosition, latestPosition))));
} else {
if (onMultiVerticalDragEnd == null) {
return;
}
onMultiVerticalDragEnd(initialPosition, latestPosition, delta);
}
_pointerCount = 0;
}
void _onCancel() {
if (_pointerCount == 1) {
if (onVerticalDragCancel == null) {
return;
}
onVerticalDragCancel();
} else {
if (onMultiVerticalDragCancel == null) {
return;
}
onMultiVerticalDragCancel();
}
_pointerCount = 0;
}
/// Method to confirm that the minimum pointer requirements is matched
void confirmAdditionalPointers() {
if (_pointerCount <= supportedPointerCount) {
// do something when minimum pointer requirements is not matched
}
}
}
/// Class for recognizing multi touch vertical gestures
class CustomHorizontalMultiDragRecognizer
extends HorizontalMultiDragGestureRecognizer {
/// Amount of current simultaneous pointers/touches
int pointerCount = 0;
/// Amount of minimum required simultaneous pointers/touches
final int supportedPointerCount;
/// A delayed process handler to execute single touch alternative
/// of a gesture if multi touch gesture's minimum was not recognized properly
/// within a limited amount of time
DelayedProcessHandler _delayedProcessHandler;
/// Multi touch horizontal drag start
final GestureMultiDragStartCallback onMultiHorizontalDragStart;
/// Multi touch horizontal drag update
final GestureMultiDragUpdateCallback onMultiHorizontalDragUpdate;
/// Multi touch horizontal drag end
final GestureMultiDragEndCallback onMultiHorizontalDragEnd;
/// Multi touch horizontal drag cancel
final GestureMultiDragCancelCallback onMultiHorizontalDragCancel;
/// Single touch horizontal drag start
final GestureDragStartCallback onHorizontalDragStart;
/// Single touch horizontal drag update
final GestureDragUpdateCallback onHorizontalDragUpdate;
/// Single touch horizontal drag end
final GestureDragEndCallback onHorizontalDragEnd;
/// Single touch horizontal drag cancel
final GestureDragCancelCallback onHorizontalDragCancel;
/// Public constructor
CustomHorizontalMultiDragRecognizer(
Object debugOwner,
this.onMultiHorizontalDragStart,
this.onMultiHorizontalDragUpdate,
this.onMultiHorizontalDragEnd,
this.onMultiHorizontalDragCancel,
this.onHorizontalDragStart,
this.onHorizontalDragUpdate,
this.onHorizontalDragEnd,
this.onHorizontalDragCancel,
this.supportedPointerCount,
) : assert(onMultiHorizontalDragStart != null ||
onMultiHorizontalDragUpdate != null),
super(debugOwner: debugOwner) {
_delayedProcessHandler ??= DelayedProcessHandler(
delayedProcess: confirmAdditionalPointers,
waitDuration: Duration(milliseconds: 100));
onStart = _handleMultiDragOnStart;
}
Drag _handleMultiDragOnStart(Offset position) {
if (pointerCount < supportedPointerCount) {
pointerCount++;
_delayedProcessHandler.startWaiting();
}
return ItemDrag(_onDragUpdate, _onDragEnd, _onCancel);
}
void _onDragUpdate(
Offset initialPosition,
Offset latestPosition,
double delta,
) {
if (pointerCount == 1) {
if (onHorizontalDragUpdate == null) {
return;
}
onHorizontalDragUpdate(DragUpdateDetails(
globalPosition: latestPosition,
delta: Offset(delta, 0.0),
primaryDelta: delta));
} else {
onMultiHorizontalDragUpdate(initialPosition, latestPosition, delta);
}
}
void _onDragEnd(
Offset initialPosition,
Offset latestPosition,
double delta,
) {
if (pointerCount == 1) {
if (onHorizontalDragEnd == null) {
return;
}
onHorizontalDragEnd(DragEndDetails(
velocity: Velocity(
pixelsPerSecond:
fromDifference(initialPosition, latestPosition))));
} else {
if (onMultiHorizontalDragEnd == null) {
return;
}
onMultiHorizontalDragEnd(initialPosition, latestPosition, delta);
}
pointerCount = 0;
}
void _onCancel() {
if (pointerCount == 1) {
if (onHorizontalDragCancel == null) {
return;
}
onHorizontalDragCancel();
} else {
if (onMultiHorizontalDragCancel == null) {
return;
}
onMultiHorizontalDragCancel();
}
pointerCount = 0;
}
/// Method to confirm that the minimum pointer requirements is matched
void confirmAdditionalPointers() {
if (pointerCount == supportedPointerCount) {
pointerCount = 0;
}
}
}
/// This Class is required to detect single or simultaneous multi touch
/// events on the surface
class ItemDrag extends Drag {
Offset _initialPosition;
Offset _latestPosition;
double _delta = 0;
/// A drag update gesture, it can be any of following:
/// - vertical multi drag update
/// - vertical single drag update
/// - horizontal multi drag update
/// - horizontal single drag update
final GestureMultiDragUpdateCallback onDragUpdate;
/// A drag update gesture, it can be any of following:
/// - vertical multi drag end
/// - vertical single drag end
/// - horizontal multi drag end
/// - horizontal single drag end
final GestureMultiDragEndCallback onDragEnd;
/// A drag update gesture, it can be any of following:
/// - vertical multi drag cancel
/// - vertical single drag cancel
/// - horizontal multi drag cancel
/// - horizontal single drag cancel
final GestureMultiDragCancelCallback onCancel;
/// public constructor
ItemDrag(this.onDragUpdate, this.onDragEnd, this.onCancel);
@override
void update(DragUpdateDetails details) {
_initialPosition ??= details.globalPosition;
_latestPosition = details.globalPosition;
// delta = details.delta.dx;
_delta = _latestPosition.dx - _initialPosition.dx;
onDragUpdate(_initialPosition, _latestPosition, _delta);
super.update(details);
}
@override
void cancel() {
onCancel();
reset();
super.cancel();
}
@override
void end(DragEndDetails details) {
onDragEnd(_initialPosition, _latestPosition, _delta);
reset();
super.end(details);
}
/// Method to set the gesture data to it's initial state
void reset() {
_initialPosition = null;
_latestPosition = null;
_delta = 0;
}
}
/// Method to get a multi horizontal drag gesture
GestureRecognizerFactoryWithHandlers<CustomHorizontalMultiDragRecognizer>
getMultiHorizontalDragGestureRecognizer(
Object debugOwner, {
GestureMultiDragStartCallback onMultiHorizontalDragStart,
GestureMultiDragUpdateCallback onMultiHorizontalDragUpdate,
GestureMultiDragEndCallback onMultiHorizontalDragEnd,
GestureMultiDragCancelCallback onMultiHorizontalDragCancel,
GestureDragStartCallback onHorizontalDragStart,
GestureDragUpdateCallback onHorizontalDragUpdate,
GestureDragEndCallback onHorizontalDragEnd,
GestureDragCancelCallback onHorizontalDragCancel,
int supportedPointerCount,
}) {
return GestureRecognizerFactoryWithHandlers<
CustomHorizontalMultiDragRecognizer>(
() => CustomHorizontalMultiDragRecognizer(
debugOwner,
onMultiHorizontalDragStart,
onMultiHorizontalDragUpdate,
onMultiHorizontalDragEnd,
onMultiHorizontalDragCancel,
onHorizontalDragStart,
onHorizontalDragUpdate,
onHorizontalDragEnd,
onHorizontalDragCancel,
supportedPointerCount,
),
(CustomHorizontalMultiDragRecognizer instance) {},
);
}
/// Method to get a multi vertical drag gesture
GestureRecognizerFactoryWithHandlers<CustomVerticalMultiDragRecognizer>
getMultiVerticalDragGestureRecognizer(
Object debugOwner, {
GestureMultiDragStartCallback onMultiVerticalDragStart,
GestureMultiDragUpdateCallback onMultiVerticalDragUpdate,
GestureMultiDragEndCallback onMultiVerticalDragEnd,
GestureMultiDragCancelCallback onMultiVerticalDragCancel,
GestureDragStartCallback onVerticalDragStart,
GestureDragUpdateCallback onVerticalDragUpdate,
GestureDragEndCallback onVerticalDragEnd,
GestureDragCancelCallback onVerticalDragCancel,
int supportedPointerCount,
}) {
return GestureRecognizerFactoryWithHandlers<
CustomVerticalMultiDragRecognizer>(
() => CustomVerticalMultiDragRecognizer(
debugOwner,
supportedPointerCount,
onMultiVerticalDragStart,
onMultiVerticalDragUpdate,
onMultiVerticalDragEnd,
onMultiVerticalDragCancel,
onVerticalDragStart,
onVerticalDragUpdate,
onVerticalDragEnd,
onVerticalDragCancel,
),
(CustomVerticalMultiDragRecognizer instance) {},
);
}
/// a Method to find Difference in offset based on given [initial] and [latest]
/// offset values
Offset fromDifference(Offset initial, Offset latest) {
return Offset((latest.dx - initial.dx), (latest.dy - initial.dy));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment