dnd_kit 0.1.0-dev.1
dnd_kit: ^0.1.0-dev.1 copied to clipboard
Flutter drag-and-drop toolkit with core widgets, sensors, measuring, overlays, and sortable presets.
dnd_kit #
dnd_kit is a Flutter drag-and-drop toolkit for building sortable lists,
grids, Kanban boards, dashboards, canvas editors, and other drag-heavy
interfaces.
Try the hosted example gallery: https://vanvixi.github.io/dnd_kit.flutter/
The package is centered on Flutter-native widgets and controllers:
DndScopeandDndControllercoordinate drag state.DndDraggableregisters draggable widgets.DndDroppableregisters drop targets.DndDragOverlayrenders an independent drag visual.SortableScopeandSortableItemprovide stable same-container list and grid sorting presets.
Applications own their data. The library reports drag, drop, and sortable move intent; your app updates its own lists, boards, stores, or documents.
Import #
import 'package:dnd_kit/dnd_kit.dart';
The main package also exports the pure Dart dnd_kit_core primitives such as
DndId, DndRect, collision detectors, modifiers, events, and drag state.
Basic Drag And Drop #
Wrap the drag-and-drop area in a DndScope, then place draggables and
droppables inside it.
DndScope(
child: Stack(
children: [
DndDroppable(
id: const DndId('inbox'),
builder: (context, details, child) {
return DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
color: details.isOver ? const Color(0xff2563eb) : const Color(0xffd1d5db),
),
),
child: child,
);
},
child: const SizedBox(width: 240, height: 160),
),
DndDraggable(
id: const DndId('task-1'),
onDragEnd: (event) {
final overId = event.overId;
if (overId == const DndId('inbox')) {
// Update application-owned state here.
}
},
child: const Card(child: ListTile(title: Text('Task 1'))),
),
DndDragOverlay(
builder: (context, details) {
return const Card(child: ListTile(title: Text('Task 1')));
},
),
],
),
)
Use DndDraggable.builder and DndDroppable.builder when visuals need to
react to active, dragging, dropping, or over states.
Sortable Lists And Grids #
Use SortableScope to provide the current item order and SortableItem for
each child. The callback tells the app what moved; it does not mutate the list.
SortableScope(
itemIds: items.map((item) => DndId(item.id)),
strategy: SortableStrategies.verticalList,
onMove: (details) {
setState(() {
final item = items.removeAt(details.fromIndex);
items.insert(details.toIndex, item);
});
},
child: ListView(
children: [
for (final item in items)
SortableItem(
id: DndId(item.id),
child: ListTile(title: Text(item.title)),
),
],
),
)
Stable strategies include:
SortableStrategies.verticalListSortableStrategies.horizontalListSortableStrategies.grid
Customization #
Core behavior is intentionally open:
- pass a custom
DndCollisionDetectortoDndController; - compose built-in detectors with
DndCollisionDetectors.compose; - constrain movement with
DndModifiervalues such asDndModifiers.restrictToVerticalAxisorDndModifiers.snapToGrid; - use
DndLongPressActivationorDndSensorActivationConstraintto tune activation; - attach
DndDiagnosticsConfig.onWarningto surface duplicate ID and registry warnings.