[{"data":1,"prerenderedAt":73},["ShallowReactive",2],{"tutorial-selezionare-piu-elementi-in-una-lista-flutter-con-selezione-multipla-e-appbar-contestuale":3,"comments-tutorial-selezionare-piu-elementi-in-una-lista-flutter-con-selezione-multipla-e-appbar-contestuale":72},{"id":4,"title":5,"slug":6,"excerpt":7,"intro":8,"cover_image":9,"cover_remote_url":10,"cover_credit":11,"video_url":15,"video":15,"difficulty":16,"estimated_minutes":17,"flutter_version":18,"status":19,"published_at":20,"meta_title":21,"meta_description":22,"category":23,"author":27,"steps":29},61,"Selezionare più elementi in una lista Flutter con selezione multipla e AppBar contestuale","selezionare-piu-elementi-in-una-lista-flutter-con-selezione-multipla-e-appbar-contestuale","Impara a implementare una lista con selezione multipla in Flutter: tocco prolungato per attivare la modalità selezione, checkbox visivi e una AppBar contestuale con azioni di gruppo.","## Introduzione\n\nLa **selezione multipla** è un pattern UX molto comune nelle app mobili: pensa a Gmail, Google Foto o l'app File. L'utente attiva la modalità selezione con un tocco prolungato, poi seleziona più elementi e applica un'azione di gruppo (eliminare, condividere, archiviare).\n\nIn questo tutorial costruiremo da zero una lista di elementi con:\n\n- **Attivazione** della modalità selezione tramite tocco prolungato (long press)\n- **Feedback visivo** sugli elementi selezionati\n- Una **AppBar contestuale** che mostra il conteggio e le azioni disponibili\n- Gestione pulita dello stato con un semplice `StatefulWidget`\n\nNon useremo pacchetti esterni: solo widget nativi Flutter. Al termine avrai un componente riutilizzabile per qualsiasi lista che richieda operazioni batch.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Ftutorials\u002Fd7836afc-84c0-40a5-ac3a-ec8d0e164f3e.jpg","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1639815188546-c43c240ff4df?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w5NzA2NTJ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3ODczMjczMDB8&ixlib=rb-4.1.0&q=80&w=1080",{"name":12,"author_url":13,"photo_url":14},"Shubham Dhage","https:\u002F\u002Funsplash.com\u002F@theshubhamdhage","https:\u002F\u002Funsplash.com\u002Fphotos\u002Fa-group-of-blue-cubes-with-numbers-on-them-JlijbOtSWuw",null,"intermediate",35,"3.x","published","2026-08-12T04:30:50+00:00","Selezione multipla in una lista Flutter: guida pratica","Come implementare la selezione multipla in una lista Flutter con long press, AppBar contestuale e azioni di gruppo, senza pacchetti esterni.",{"id":24,"name":25,"slug":26},1,"Guide","guide",{"id":24,"name":28},"Flutter Bot",[30,37,44,51,58,65],{"id":31,"position":24,"title":32,"body":33,"code_snippet":34,"code_language":35,"expected_result":36,"demo_url":15,"video_url":15},408,"Preparare il modello dati e la schermata di base","Iniziamo definendo un semplice modello `Task` e la struttura della schermata. Ogni elemento avrà un identificativo e un titolo. Generiamo una lista di esempio per lavorare subito con dati concreti.\n\nUsiamo uno `StatefulWidget` perché dovremo tenere traccia dello stato della selezione, che cambierà durante l'interazione dell'utente.","class Task {\n  final int id;\n  final String title;\n\n  const Task({required this.id, required this.title});\n}\n\nclass MultiSelectPage extends StatefulWidget {\n  const MultiSelectPage({super.key});\n\n  @override\n  State\u003CMultiSelectPage> createState() => _MultiSelectPageState();\n}\n\nclass _MultiSelectPageState extends State\u003CMultiSelectPage> {\n  final List\u003CTask> _tasks = List.generate(\n    20,\n    (i) => Task(id: i, title: 'Attività numero $i'),\n  );\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('Le mie attività')),\n      body: ListView.builder(\n        itemCount: _tasks.length,\n        itemBuilder: (context, index) {\n          final task = _tasks[index];\n          return ListTile(title: Text(task.title));\n        },\n      ),\n    );\n  }\n}","dart","Una schermata con una AppBar e una lista scrollabile di 20 attività, senza alcuna selezione ancora attiva.",{"id":38,"position":39,"title":40,"body":41,"code_snippet":42,"code_language":35,"expected_result":43,"demo_url":15,"video_url":15},409,2,"Aggiungere lo stato della selezione","Introduciamo un `Set\u003Cint>` per memorizzare gli **id** degli elementi selezionati. Usiamo un `Set` invece di una `List` perché garantisce l'unicità e offre operazioni di aggiunta\u002Frimozione efficienti.\n\nDeriviamo due proprietà utili:\n\n- `_isSelectionMode`: vera quando c'è almeno un elemento selezionato\n- `_isSelected(id)`: verifica se un dato elemento è selezionato\n\nAggiungiamo anche un metodo `_toggleSelection` che aggiunge o rimuove un id, chiamato dentro `setState` per aggiornare la UI.","final Set\u003Cint> _selectedIds = {};\n\nbool get _isSelectionMode => _selectedIds.isNotEmpty;\n\nbool _isSelected(int id) => _selectedIds.contains(id);\n\nvoid _toggleSelection(int id) {\n  setState(() {\n    if (_selectedIds.contains(id)) {\n      _selectedIds.remove(id);\n    } else {\n      _selectedIds.add(id);\n    }\n  });\n}\n\nvoid _clearSelection() {\n  setState(() => _selectedIds.clear());\n}","Il codice compila e lo stato della selezione è pronto per essere usato, anche se non è ancora collegato all'interfaccia.",{"id":45,"position":46,"title":47,"body":48,"code_snippet":49,"code_language":35,"expected_result":50,"demo_url":15,"video_url":15},410,3,"Gestire long press e tocco negli elementi della lista","Ora colleghiamo l'interazione. La logica è questa:\n\n- Il **long press** su un elemento attiva la modalità selezione e seleziona quell'elemento.\n- Un **tocco singolo** ha comportamento diverso a seconda della modalità: se la selezione è attiva, aggiunge\u002Frimuove l'elemento; altrimenti apre il dettaglio (o compie l'azione normale).\n\nAggiungiamo anche un feedback visivo: mostriamo una `Checkbox` come `leading` quando la selezione è attiva e coloriamo la riga selezionata.","Widget _buildTile(Task task) {\n  final selected = _isSelected(task.id);\n  return ListTile(\n    onLongPress: () => _toggleSelection(task.id),\n    onTap: () {\n      if (_isSelectionMode) {\n        _toggleSelection(task.id);\n      } else {\n        \u002F\u002F azione normale, es. apertura dettaglio\n        ScaffoldMessenger.of(context).showSnackBar(\n          SnackBar(content: Text('Apri ${task.title}')),\n        );\n      }\n    },\n    selected: selected,\n    selectedTileColor: Theme.of(context).colorScheme.primaryContainer,\n    leading: _isSelectionMode\n        ? Checkbox(\n            value: selected,\n            onChanged: (_) => _toggleSelection(task.id),\n          )\n        : CircleAvatar(child: Text('${task.id}')),\n    title: Text(task.title),\n  );\n}","Tenendo premuto un elemento appare la checkbox e la riga si evidenzia. In modalità selezione, i tocchi selezionano\u002Fdeselezionano gli elementi.",{"id":52,"position":53,"title":54,"body":55,"code_snippet":56,"code_language":35,"expected_result":57,"demo_url":15,"video_url":15},411,4,"Creare la AppBar contestuale","Quando la selezione è attiva, sostituiamo la AppBar standard con una **AppBar contestuale** che mostra:\n\n- Un pulsante **chiudi** (X) per uscire dalla modalità selezione\n- Il **conteggio** degli elementi selezionati come titolo\n- Le **azioni di gruppo** (elimina, seleziona tutto) negli `actions`\n\nUsiamo una funzione che restituisce la AppBar giusta in base a `_isSelectionMode`. Poiché entrambe implementano `PreferredSizeWidget`, possiamo assegnarle direttamente alla proprietà `appBar` dello `Scaffold`.","PreferredSizeWidget _buildAppBar() {\n  if (!_isSelectionMode) {\n    return AppBar(title: const Text('Le mie attività'));\n  }\n\n  return AppBar(\n    backgroundColor: Theme.of(context).colorScheme.secondaryContainer,\n    leading: IconButton(\n      icon: const Icon(Icons.close),\n      onPressed: _clearSelection,\n    ),\n    title: Text('${_selectedIds.length} selezionati'),\n    actions: [\n      IconButton(\n        icon: const Icon(Icons.select_all),\n        tooltip: 'Seleziona tutto',\n        onPressed: _selectAll,\n      ),\n      IconButton(\n        icon: const Icon(Icons.delete),\n        tooltip: 'Elimina',\n        onPressed: _deleteSelected,\n      ),\n    ],\n  );\n}\n\nvoid _selectAll() {\n  setState(() {\n    _selectedIds.addAll(_tasks.map((t) => t.id));\n  });\n}","Attivando la selezione, la AppBar cambia colore e mostra il conteggio con i pulsanti di azione. Il pulsante X annulla la selezione.",{"id":59,"position":60,"title":61,"body":62,"code_snippet":63,"code_language":35,"expected_result":64,"demo_url":15,"video_url":15},412,5,"Implementare l'azione di eliminazione di gruppo","Colleghiamo il pulsante elimina a una funzione che rimuove tutti gli elementi selezionati dalla lista. Dopo l'eliminazione svuotiamo la selezione (uscendo automaticamente dalla modalità) e mostriamo uno `SnackBar` di conferma.\n\nRimuoviamo gli elementi con `removeWhere`, controllando l'appartenenza al set degli id selezionati.","void _deleteSelected() {\n  final count = _selectedIds.length;\n  setState(() {\n    _tasks.removeWhere((task) => _selectedIds.contains(task.id));\n    _selectedIds.clear();\n  });\n  ScaffoldMessenger.of(context).showSnackBar(\n    SnackBar(content: Text('$count elementi eliminati')),\n  );\n}","Selezionando alcuni elementi e premendo il cestino, questi vengono rimossi dalla lista e appare un messaggio di conferma.",{"id":66,"position":67,"title":68,"body":69,"code_snippet":70,"code_language":35,"expected_result":71,"demo_url":15,"video_url":15},413,6,"Gestire il tasto indietro e montare tutto insieme","Un ultimo dettaglio UX importante: quando la selezione è attiva, il tasto **indietro** del dispositivo (o il gesto di ritorno) dovrebbe annullare la selezione invece di uscire dalla schermata. Usiamo `PopScope` per intercettare il tentativo di pop.\n\nEcco il `build` finale che assembla la AppBar contestuale, la lista e la gestione del back.","@override\nWidget build(BuildContext context) {\n  return PopScope(\n    canPop: !_isSelectionMode,\n    onPopInvokedWithResult: (didPop, result) {\n      if (!didPop && _isSelectionMode) {\n        _clearSelection();\n      }\n    },\n    child: Scaffold(\n      appBar: _buildAppBar(),\n      body: ListView.builder(\n        itemCount: _tasks.length,\n        itemBuilder: (context, index) => _buildTile(_tasks[index]),\n      ),\n    ),\n  );\n}","Con la selezione attiva, premere indietro annulla la selezione senza chiudere la schermata. L'app offre ora un'esperienza di selezione multipla completa e coerente.",[],1789120602291]