Skip to content

Instantly share code, notes, and snippets.

@GAM3RG33K
Last active January 23, 2025 11:19
Show Gist options
  • Save GAM3RG33K/5281f1fc01ca026cdbad122abc110b9a to your computer and use it in GitHub Desktop.
Save GAM3RG33K/5281f1fc01ca026cdbad122abc110b9a 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));
}
@Lukas-io
Copy link

Lukas-io commented May 3, 2024

thanks man

@Lukas-io
Copy link

Lukas-io commented May 3, 2024

I just spent the last 2 hours updating the code for Flutter 3 but still doesn't work. no errors though 'hipppee' but still running it though

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment