[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-effetti-shimmer-e-skeleton-loading-in-flutter-con-skeletonizer":3,"comments-article-effetti-shimmer-e-skeleton-loading-in-flutter-con-skeletonizer":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},54,"Effetti shimmer e skeleton loading in Flutter con Skeletonizer","effetti-shimmer-e-skeleton-loading-in-flutter-con-skeletonizer","Migliora la percezione di velocità della tua app mostrando placeholder animati durante il caricamento dei dati. Guida pratica al pacchetto Skeletonizer per creare effetti skeleton eleganti e senza sforzo.","## Perché usare gli skeleton loader\n\nQuando un'app carica dati dalla rete, mostrare uno spinner al centro dello schermo è la soluzione più semplice ma spesso poco soddisfacente. Gli **skeleton loader** (o \"scheletri\") riproducono la struttura della UI finale con forme grigie animate, comunicando all'utente cosa sta per apparire e riducendo la percezione del tempo di attesa.\n\nL'effetto **shimmer** — quel bagliore che scorre sui placeholder — è ormai uno standard adottato da app come Facebook, LinkedIn e YouTube. In Flutter possiamo implementarlo manualmente, ma il pacchetto [`skeletonizer`](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fskeletonizer) semplifica enormemente il lavoro: trasforma automaticamente qualsiasi widget in uno scheletro, senza duplicare i layout.\n\n## Installazione\n\nAggiungi la dipendenza al `pubspec.yaml`:\n\n```yaml\ndependencies:\n  skeletonizer: ^1.4.2\n```\n\nPoi esegui:\n\n```bash\nflutter pub get\n```\n\n## Il concetto chiave: un solo layout\n\nA differenza degli approcci tradizionali, dove si scrive un widget separato per lo stato di caricamento, Skeletonizer usa **lo stesso layout** sia per i dati reali sia per lo scheletro. Basta avvolgere l'albero dei widget in un `Skeletonizer` e impostare la proprietà `enabled`.\n\n```dart\nimport 'package:flutter\u002Fmaterial.dart';\nimport 'package:skeletonizer\u002Fskeletonizer.dart';\n\nclass ArticoloList extends StatelessWidget {\n  final bool isLoading;\n  final List\u003CArticolo> articoli;\n\n  const ArticoloList({\n    super.key,\n    required this.isLoading,\n    required this.articoli,\n  });\n\n  @override\n  Widget build(BuildContext context) {\n    return Skeletonizer(\n      enabled: isLoading,\n      child: ListView.builder(\n        itemCount: isLoading ? 6 : articoli.length,\n        itemBuilder: (context, index) {\n          final articolo = isLoading\n              ? const Articolo.placeholder()\n              : articoli[index];\n          return Card(\n            child: ListTile(\n              leading: const CircleAvatar(),\n              title: Text(articolo.titolo),\n              subtitle: Text(articolo.autore),\n            ),\n          );\n        },\n      ),\n    );\n  }\n}\n```\n\nQuando `enabled` è `true`, Skeletonizer disegna automaticamente forme grigie animate al posto di testi, avatar e immagini. Quando diventa `false`, viene mostrato il contenuto reale con una transizione fluida.\n\n### Dati placeholder\n\nDurante il caricamento serve comunque una struttura da renderizzare. Un pattern comune è definire un factory che genera dati fittizi:\n\n```dart\nclass Articolo {\n  final String titolo;\n  final String autore;\n\n  const Articolo({required this.titolo, required this.autore});\n\n  factory Articolo.placeholder() => const Articolo(\n        titolo: 'Titolo di esempio articolo',\n        autore: 'Nome autore',\n      );\n}\n```\n\nIl testo non conta: Skeletonizer misura solo la larghezza per disegnare la barra grigia.\n\n## Personalizzare l'effetto shimmer\n\nIl comportamento predefinito usa un'animazione shimmer, ma possiamo configurarla tramite la proprietà `effect`:\n\n```dart\nSkeletonizer(\n  enabled: isLoading,\n  effect: ShimmerEffect(\n    baseColor: Colors.grey.shade300,\n    highlightColor: Colors.grey.shade100,\n    duration: const Duration(seconds: 1),\n  ),\n  child: myWidget,\n)\n```\n\nAltri effetti disponibili sono:\n\n- **`PulseEffect`**: un dissolvimento pulsante, meno appariscente dello shimmer;\n- **`SoldColorEffect`**: colore statico senza animazione, utile per ridurre il consumo di risorse.\n\n## Controllo fine con le annotazioni\n\nA volte alcuni widget non vanno \"scheletrizzati\" o richiedono forme specifiche. Skeletonizer offre delle annotazioni:\n\n```dart\nColumn(\n  children: [\n    \u002F\u002F Ignora questo widget: resta sempre visibile\n    Skeleton.keep(\n      child: const Icon(Icons.favorite),\n    ),\n    \u002F\u002F Nasconde completamente durante il loading\n    Skeleton.ignore(\n      child: const Divider(),\n    ),\n    \u002F\u002F Forza uno scheletro rettangolare\n    Skeleton.leaf(\n      child: Container(\n        width: 100,\n        height: 100,\n        color: Colors.blue,\n      ),\n    ),\n  ],\n)\n```\n\n- **`Skeleton.keep`**: mantiene il widget renderizzato normalmente;\n- **`Skeleton.ignore`**: lo esclude dallo scheletro;\n- **`Skeleton.leaf`**: lo tratta come un nodo foglia unico, evitando che i figli generino scheletri separati;\n- **`Skeleton.replace`**: sostituisce il widget con una forma di dimensioni fisse durante il loading.\n\n## Integrazione con dati asincroni\n\nNella pratica lo stato di caricamento arriva da una chiamata di rete. Ecco un esempio con `FutureBuilder`:\n\n```dart\nFutureBuilder\u003CList\u003CArticolo>>(\n  future: repository.caricaArticoli(),\n  builder: (context, snapshot) {\n    final isLoading = !snapshot.hasData;\n    final articoli = snapshot.data ?? [];\n    return ArticoloList(\n      isLoading: isLoading,\n      articoli: articoli,\n    );\n  },\n)\n```\n\nLo stesso approccio si adatta perfettamente a Riverpod, BLoC o qualunque gestore di stato: è sufficiente mappare lo stato \"loading\" sulla proprietà `enabled`.\n\n## Best practice\n\n- **Mantieni gli scheletri fedeli al layout finale**: un numero di righe o dimensioni molto diverse crea un fastidioso \"salto\" quando i dati arrivano.\n- **Non esagerare con la durata**: uno skeleton mostrato per meno di 300 ms genera un flash sgradevole. Valuta un tempo minimo di visualizzazione.\n- **Usa `PulseEffect` per liste lunghe**: lo shimmer su molti elementi può risultare pesante e visivamente rumoroso.\n- **Testa in dark mode**: adatta `baseColor` e `highlightColor` al tema corrente per evitare contrasti eccessivi.\n\n## Conclusioni\n\nSkeletonizer elimina la duplicazione dei layout tipica degli skeleton loader tradizionali, rendendo l'implementazione quasi immediata. Con poche righe di codice si ottiene un'esperienza di caricamento moderna e professionale, migliorando la percezione di velocità dell'app senza appesantire la codebase.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002Fadb114dd-8afe-4c32-a60d-6cc997eaa1e8.jpg",null,"published","2026-07-28T04:00:44+00:00","Skeleton loading in Flutter con Skeletonizer","Guida pratica a Skeletonizer per creare effetti shimmer e skeleton loading in Flutter senza duplicare i layout. Esempi, personalizzazioni e best practice.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1785219595742]