Le griglie sono uno dei pattern di layout più comuni nelle app moderne: gallerie di foto, cataloghi di prodotti, dashboard di card. In questo tutorial vedremo come usare GridView in tutte le sue varianti, come rendere il numero di colonne adattivo con SliverGridDelegateWithMaxCrossAxisExtent, e come integrare una griglia dentro un CustomScrollView tramite SliverGrid. Alla fine avrai una galleria responsive che si adatta a smartphone, tablet e desktop.
Foto di Filipe Nobre su Unsplash
Creare griglie dinamiche e responsive in Flutter con GridView e SliverGrid
- 1
Prepara il progetto e i dati di esempio
Partiamo da un semplice progetto Flutter. Creiamo un modello
Producte una lista di dati fittizi che useremo per popolare le nostre griglie. Non servono pacchetti esterni:GridVieweSliverGridfanno parte del framework.class Product { final String name; final Color color; final double price; const Product({ required this.name, required this.color, required this.price, }); } final List<Product> demoProducts = List.generate( 30, (i) => Product( name: 'Prodotto ${i + 1}', color: Colors.primaries[i % Colors.primaries.length].shade300, price: (i + 1) * 4.99, ), );Risultato atteso
Hai una lista `demoProducts` con 30 elementi pronti da mostrare in griglia.
- 2
Crea una griglia con GridView.builder e conteggio fisso di colonne
Il modo più diretto per creare una griglia performante è
GridView.builder, che costruisce le celle solo quando servono (lazy). UsiamoSliverGridDelegateWithFixedCrossAxisCountper definire un numero fisso di colonne, la spaziatura e il rapporto d'aspetto delle celle.class FixedGridScreen extends StatelessWidget { const FixedGridScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Griglia fissa')), body: GridView.builder( padding: const EdgeInsets.all(12), itemCount: demoProducts.length, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 0.8, ), itemBuilder: (context, index) { final product = demoProducts[index]; return ProductCard(product: product); }, ), ); } }Risultato atteso
Vedi una griglia a 2 colonne che scorre verticalmente con celle spaziate.
- 3
Costruisci la card riutilizzabile
Estraiamo la singola cella in un widget
ProductCardriutilizzabile. Usare un widget dedicato mantiene il codice pulito e rende ilitemBuilderleggibile.class ProductCard extends StatelessWidget { final Product product; const ProductCard({super.key, required this.product}); @override Widget build(BuildContext context) { return Card( clipBehavior: Clip.antiAlias, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded( child: Container( color: product.color, child: const Center( child: Icon(Icons.image, color: Colors.white, size: 40), ), ), ), Padding( padding: const EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( product.name, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontWeight: FontWeight.bold), ), const SizedBox(height: 4), Text('€ ${product.price.toStringAsFixed(2)}'), ], ), ), ], ), ); } }Risultato atteso
Ogni cella mostra un'area colorata, il nome del prodotto e il prezzo.
- 4
Rendi il numero di colonne adattivo allo spazio disponibile
Un numero fisso di colonne non è ideale su tablet o desktop. Con
SliverGridDelegateWithMaxCrossAxisExtentindichi la larghezza massima che ogni cella può avere: Flutter calcola automaticamente quante colonne stanno nello spazio disponibile. Così la griglia diventa naturalmente responsive senza scrivere logica suMediaQuery.GridView.builder( padding: const EdgeInsets.all(12), itemCount: demoProducts.length, gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 200, // ogni cella al massimo 200px di larghezza mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 0.8, ), itemBuilder: (context, index) => ProductCard(product: demoProducts[index]), )Risultato atteso
Su schermi stretti vedi 2 colonne, mentre allargando la finestra ne compaiono automaticamente 3, 4 o più.
- 5
Integra la griglia in un CustomScrollView con SliverGrid
Quando devi combinare la griglia con altri contenuti scrollabili (una
SliverAppBar, un'intestazione, una lista) devi usareSliverGriddentro unCustomScrollView. La logica del delegate è identica, ma i figli si passano tramiteSliverChildBuilderDelegate.class SliverGridScreen extends StatelessWidget { const SliverGridScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: [ const SliverAppBar( floating: true, title: Text('Catalogo'), ), SliverPadding( padding: const EdgeInsets.all(12), sliver: SliverGrid( gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 200, mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 0.8, ), delegate: SliverChildBuilderDelegate( (context, index) => ProductCard(product: demoProducts[index]), childCount: demoProducts.length, ), ), ), ], ), ); } }Risultato atteso
La griglia scorre insieme alla SliverAppBar in un unico scroll fluido.
- 6
Aggiungi celle di dimensioni variabili con SliverGrid staggered (opzionale)
Per griglie tipo Pinterest, dove le celle hanno altezze diverse, il framework di base non basta. Un approccio comune è il pacchetto
flutter_staggered_grid_view. Aggiungilo conflutter pub add flutter_staggered_grid_viewe usaMasonryGridViewper un layout a mattoncini.import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; MasonryGridView.count( padding: const EdgeInsets.all(12), crossAxisCount: 2, mainAxisSpacing: 12, crossAxisSpacing: 12, itemCount: demoProducts.length, itemBuilder: (context, index) { // altezza variabile per un effetto "mattoncini" final height = 120.0 + (index % 4) * 40; return SizedBox( height: height, child: ProductCard(product: demoProducts[index]), ); }, )Risultato atteso
Ottieni una griglia in stile Pinterest con celle di altezza variabile ben incastrate.
- 7
Applica le best practice per performance e leggibilità
Alcuni accorgimenti finali per griglie robuste:
- Usa sempre
GridView.builder/SliverGridcon builder per liste lunghe: evita di costruire tutte le celle in memoria. - Preferisci
maxCrossAxisExtental conteggio fisso per la responsività cross-device. - Imposta
keyunivoche sulle celle se gli elementi possono essere riordinati o rimossi. - Aggiungi
cacheExtentse vuoi precaricare più celle fuori schermo per uno scroll più fluido. - Estrai le celle in widget dedicati per abilitare il riutilizzo e ottimizzare i rebuild.
GridView.builder( cacheExtent: 600, // precarica celle fuori dallo schermo itemCount: demoProducts.length, gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 200, mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 0.8, ), itemBuilder: (context, index) { final product = demoProducts[index]; return ProductCard( key: ValueKey(product.name), product: product, ); }, )Risultato atteso
Hai una griglia responsive, performante e manutenibile pronta per la produzione.
- Usa sempre
Commenti (0)
Ancora nessun commento. Inizia tu!