Documentation menu
Collision detection
When a draggable overlaps several droppables, a collision detector decides which one wins. Detection is shared math in the engine, so Flutter and Jaspr resolve the same target from the same input.
- —The built-in collision detectors and when to use each.
- —How to set a detector on a scope.
- —How to combine detectors into a fallback chain.
Built-in detectors
All detectors live on DndCollisionDetectors:
- •closestCenter — the target whose center is nearest the pointer. A solid default for grids and free layouts.
- •closestCorners — compares corners instead of centers; steadier when targets vary a lot in size.
- •rectIntersection — the target the dragged rect overlaps most. Natural for list and Kanban reordering.
- •pointerWithin — only targets the pointer is literally inside. Precise, but needs a pointer (not keyboard) drag.
Candidates never include the item being dragged, so a sortable item cannot win its own collision. The dragged id is still passed along as
DndCollisionInput.activeId, which lets a custom detector scope candidates by kind when two sortable surfaces share one controller — see the
recipes.
Setting a detector
Pass a detector to the DndController
on your DndScope. The default is
closestCenter.
DndScope(
controller: DndController(
collisionDetector: DndCollisionDetectors.closestCenter,
),
child: board,
)
Composing
Use compose to try detectors in order and take the first that finds a target — for example, prefer a precise pointer hit, then fall back to overlap.
DndController(
collisionDetector: DndCollisionDetectors.compose([
DndCollisionDetectors.pointerWithin,
DndCollisionDetectors.rectIntersection,
]),
)