dispatchDrag method
Drags from (x, y) to (toX, toY).
holdMs is how long the pointer rests before moving — a long-press
draggable needs it, a plain one does not. The move is sent in steps
because a single jump does not look like a drag to a recogniser: it sees
one enormous delta and no gesture in between.
Implementation
Future<void> dispatchDrag(
double x,
double y,
double toX,
double toY, {
int holdMs = 600,
int steps = 12,
}) async {
final binding = GestureBinding.instance;
final start = Offset(x, y);
final end = Offset(toX, toY);
var stamp = SchedulerBinding.instance.currentSystemFrameTimeStamp;
final pointer = _nextPointer++;
final kind = _pointerKind();
final hitResult = HitTestResult();
// ignore: deprecated_member_use
binding.hitTest(hitResult, start);
binding.dispatchEvent(
PointerDownEvent(
timeStamp: stamp, pointer: pointer, position: start, kind: kind),
hitResult,
);
await Future<void>.delayed(Duration(milliseconds: holdMs));
var previous = start;
for (var i = 1; i <= steps; i++) {
final position = Offset.lerp(start, end, i / steps)!;
stamp += const Duration(milliseconds: 16);
binding.dispatchEvent(
PointerMoveEvent(
timeStamp: stamp,
pointer: pointer,
position: position,
delta: position - previous,
kind: kind,
),
hitResult,
);
previous = position;
await Future<void>.delayed(const Duration(milliseconds: 16));
}
stamp += const Duration(milliseconds: 16);
binding.dispatchEvent(
PointerUpEvent(
timeStamp: stamp, pointer: pointer, position: end, kind: kind),
hitResult,
);
}