resolveDragArena function
ActiveGesture?
resolveDragArena({
- required Offset totalDelta,
- required Map<
DragStart, DragGesture> registered, - double minDistance = 10,
Resolves a drag gesture from the registered map for the accumulated
motion vector. Returns the matching ActiveGesture, or null if no axis
has crossed minDistance yet, or no registered key matches.
Resolution: per-axis threshold (each axis must independently cross
minDistance to count). Candidates are tried in priority order from
most-specific to least-specific:
- Diagonal (when both axes crossed)
- Dominant (axis ≥ 2× the other)
- Primary direction (the dominant axis's specific direction)
- Secondary direction (the other axis's specific direction)
horizontal/vertical(axis-only)any
First registered match wins. No friction-based scoring — direction-key specificity is the contract.
Implementation
ActiveGesture? resolveDragArena({
required Offset totalDelta,
required Map<DragStart, DragGesture> registered,
double minDistance = 10,
}) {
final dx = totalDelta.dx;
final dy = totalDelta.dy;
final adx = dx.abs();
final ady = dy.abs();
if (adx < minDistance && ady < minDistance) return null;
final hCrossed = adx >= minDistance;
final vCrossed = ady >= minDistance;
final DragStart? hDir = hCrossed ? (dx > 0 ? .right : .left) : null;
final DragStart? vDir = vCrossed ? (dy > 0 ? .down : .up) : null;
// Diagonal — both axes crossed.
DragStart? diagonal;
if (hCrossed && vCrossed) {
diagonal = switch ((hDir, vDir)) {
(.left, .up) => .upLeft,
(.right, .up) => .upRight,
(.left, .down) => .downLeft,
(.right, .down) => .downRight,
_ => null,
};
}
// Dominant — one axis ≥ 2× the other.
DragStart? dominant;
if (hCrossed && adx >= 2 * ady) {
dominant = dx > 0 ? .rightDominant : .leftDominant;
} else if (vCrossed && ady >= 2 * adx) {
dominant = dy > 0 ? .downDominant : .upDominant;
}
// Primary / secondary by dominant-axis preference.
final hPrimary = !vCrossed || (hCrossed && adx >= ady);
final primary = hPrimary ? hDir : vDir;
final secondary = hPrimary ? vDir : hDir;
for (final candidate in <DragStart?>[
diagonal,
dominant,
primary,
secondary,
if (hCrossed) .horizontal,
if (vCrossed) .vertical,
.any,
]) {
if (candidate == null) continue;
final gesture = registered[candidate];
if (gesture != null) return (start: candidate, gesture: gesture);
}
return null;
}