[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-drag-drop-in-flutter-creare-interfacce-interattive-con-draggable-e-dragtarget":3,"comments-article-drag-drop-in-flutter-creare-interfacce-interattive-con-draggable-e-dragtarget":21},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"video_url":10,"status":11,"published_at":12,"meta_title":13,"meta_description":14,"category":15,"author":19},47,"Drag & Drop in Flutter: creare interfacce interattive con Draggable e DragTarget","drag-drop-in-flutter-creare-interfacce-interattive-con-draggable-e-dragtarget","Scopri come implementare il trascinamento degli elementi nella tua app Flutter usando i widget Draggable e DragTarget, con feedback visivi e riordino di liste.","## Introduzione\n\nIl drag & drop è un'interazione familiare per gli utenti: trascinare un elemento da un punto all'altro rende le interfacce più intuitive e coinvolgenti. Pensiamo a una board in stile Kanban, a un carrello della spesa dove si trascinano prodotti, o a una lista riordinabile.\n\nFlutter offre un supporto nativo e completo per queste interazioni tramite i widget `Draggable`, `DragTarget` e `LongPressDraggable`, oltre al comodo `ReorderableListView` per i casi più comuni. In questa guida vedremo come usarli in pratica.\n\n## I widget fondamentali\n\nIl sistema di drag & drop di Flutter si basa su due componenti principali:\n\n- **`Draggable`**: rende un widget trascinabile. Trasporta un valore (il `data`) che verrà consegnato alla destinazione.\n- **`DragTarget`**: definisce una zona in cui è possibile rilasciare gli elementi trascinati, decidendo se accettarli o meno.\n\n## Un esempio base con Draggable\n\nIl widget `Draggable` richiede tre proprietà chiave: `data` (il valore trasportato), `child` (l'aspetto normale) e `feedback` (l'aspetto durante il trascinamento).\n\n```dart\nDraggable\u003Cint>(\n  data: 10,\n  feedback: Material(\n    color: Colors.transparent,\n    child: Container(\n      width: 80,\n      height: 80,\n      color: Colors.blue.withOpacity(0.7),\n      child: const Center(\n        child: Text('Trascina', style: TextStyle(color: Colors.white)),\n      ),\n    ),\n  ),\n  childWhenDragging: Container(\n    width: 80,\n    height: 80,\n    color: Colors.grey.shade300,\n  ),\n  child: Container(\n    width: 80,\n    height: 80,\n    color: Colors.blue,\n    child: const Center(\n      child: Text('Trascina', style: TextStyle(color: Colors.white)),\n    ),\n  ),\n)\n```\n\nAlcune note importanti:\n\n- Il `feedback` viene renderizzato al di fuori dell'albero normale, quindi va spesso avvolto in un `Material` per evitare artefatti visivi come il testo con sottolineatura gialla.\n- `childWhenDragging` sostituisce il widget originale durante il trascinamento (opzionale).\n\n## Ricevere gli elementi con DragTarget\n\nIl `DragTarget` costruisce la propria UI in base agli elementi che stanno per essere rilasciati e reagisce quando avviene il drop.\n\n```dart\nint _totale = 0;\n\nDragTarget\u003Cint>(\n  builder: (context, candidateData, rejectedData) {\n    final isHovering = candidateData.isNotEmpty;\n    return Container(\n      width: 150,\n      height: 150,\n      color: isHovering ? Colors.green.shade200 : Colors.green.shade50,\n      child: Center(\n        child: Text('Totale: $_totale'),\n      ),\n    );\n  },\n  onWillAcceptWithDetails: (details) => details.data > 0,\n  onAcceptWithDetails: (details) {\n    setState(() {\n      _totale += details.data;\n    });\n  },\n)\n```\n\nI callback principali sono:\n\n- **`builder`**: riceve `candidateData` (gli elementi accettabili sopra il target) e `rejectedData` (quelli rifiutati). Utile per dare feedback visivo durante l'hover.\n- **`onWillAcceptWithDetails`**: decide se accettare o meno l'elemento in arrivo. Restituendo `false`, l'elemento finirà tra i `rejectedData`.\n- **`onAcceptWithDetails`**: viene invocato quando l'elemento viene effettivamente rilasciato.\n\n> Nota: i vecchi callback `onWillAccept` e `onAccept` sono deprecati a favore delle versioni `...WithDetails`, che forniscono anche la posizione del drop tramite `details.offset`.\n\n## LongPressDraggable per le liste\n\nQuando gli elementi trascinabili sono dentro una lista scorrevole, un `Draggable` normale entrerebbe in conflitto con lo scroll. La soluzione è `LongPressDraggable`, che avvia il trascinamento solo dopo una pressione prolungata.\n\n```dart\nLongPressDraggable\u003CTask>(\n  data: task,\n  feedback: Material(\n    elevation: 6,\n    child: TaskCard(task: task),\n  ),\n  child: TaskCard(task: task),\n)\n```\n\n## Riordinare liste con ReorderableListView\n\nPer il caso comune del riordino di una lista, Flutter offre `ReorderableListView`, che gestisce internamente tutta la logica di drag & drop.\n\n```dart\nReorderableListView(\n  onReorder: (oldIndex, newIndex) {\n    setState(() {\n      if (newIndex > oldIndex) {\n        newIndex -= 1;\n      }\n      final item = _items.removeAt(oldIndex);\n      _items.insert(newIndex, item);\n    });\n  },\n  children: [\n    for (final item in _items)\n      ListTile(\n        key: ValueKey(item),\n        title: Text(item),\n      ),\n  ],\n)\n```\n\nAttenzione a due dettagli:\n\n- Ogni figlio **deve** avere una `key` univoca, altrimenti Flutter non riesce a tracciare gli spostamenti.\n- La correzione `newIndex -= 1` quando `newIndex > oldIndex` è necessaria perché l'elemento viene prima rimosso e poi reinserito.\n\n## Best practice\n\n- **Feedback chiaro**: usa `childWhenDragging` e cambia lo stile del `DragTarget` durante l'hover per comunicare all'utente cosa sta accadendo.\n- **Material per il feedback**: avvolgi sempre il `feedback` in un `Material` per evitare problemi di rendering del testo.\n- **Accessibilità**: il drag & drop puro non è sempre accessibile; considera alternative (come pulsanti di spostamento) per gli utenti che usano screen reader.\n- **Prestazioni**: mantieni leggero il widget `feedback`, poiché viene ricostruito durante il movimento.\n\n## Conclusioni\n\nFlutter rende il drag & drop sorprendentemente semplice da implementare. Con `Draggable` e `DragTarget` hai il controllo completo su interazioni personalizzate, mentre `ReorderableListView` copre il caso d'uso più frequente del riordino con poche righe di codice. Sperimenta con i feedback visivi per creare interfacce davvero fluide e intuitive.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002Fbe1367af-b5b9-4fc1-b49f-2c8db5cfb0c0.jpg",null,"published","2026-07-21T04:00:41+00:00","Drag & Drop in Flutter: Draggable e DragTarget","Guida pratica al drag & drop in Flutter: impara a usare Draggable, DragTarget, LongPressDraggable e ReorderableListView con esempi di codice.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1785219596930]