[{"data":1,"prerenderedAt":69},["ShallowReactive",2],{"tutorial-grafica-shimmer-per-gli-stati-di-caricamento-in-flutter-con-shimmer":3,"comments-tutorial-grafica-shimmer-per-gli-stati-di-caricamento-in-flutter-con-shimmer":68},{"id":4,"title":5,"slug":6,"excerpt":7,"intro":8,"cover_image":9,"video_url":10,"difficulty":11,"estimated_minutes":12,"flutter_version":13,"status":14,"published_at":15,"meta_title":16,"meta_description":17,"category":18,"author":22,"steps":24},36,"Grafica shimmer per gli stati di caricamento in Flutter con shimmer","grafica-shimmer-per-gli-stati-di-caricamento-in-flutter-con-shimmer","Impara a creare effetti skeleton (shimmer) durante il caricamento dei dati in Flutter, migliorando la percezione di velocità della tua app con il pacchetto shimmer.","Mostrare uno spinner circolare durante il caricamento è funzionale ma poco moderno. Gli **skeleton loader** con effetto *shimmer* (quella luce che scorre sui placeholder grigi) danno all'utente l'idea che i contenuti stiano già arrivando, migliorando la percezione delle prestazioni.\n\nIn questo tutorial useremo il pacchetto [`shimmer`](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fshimmer) per costruire una schermata con una lista di card che mostra placeholder animati mentre simuliamo il caricamento dei dati da una API. Vedremo come strutturare il codice in modo pulito per passare dallo stato di *loading* allo stato di *loaded*.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Ftutorials\u002F452d7a70-0316-4cae-b717-7c1e35e7c6bb.jpg",null,"beginner",25,"3.x","published","2026-07-12T04:30:46+00:00","Effetto shimmer in Flutter: skeleton loading","Guida pratica per creare skeleton loader con effetto shimmer in Flutter usando il pacchetto shimmer e migliorare gli stati di caricamento.",{"id":19,"name":20,"slug":21},1,"Guide","guide",{"id":19,"name":23},"Flutter Bot",[25,32,40,47,54,61],{"id":26,"position":19,"title":27,"body":28,"code_snippet":29,"code_language":30,"expected_result":31,"demo_url":10,"video_url":10},244,"Aggiungere la dipendenza shimmer","Per prima cosa aggiungiamo il pacchetto `shimmer` al progetto. Puoi farlo da terminale con il comando `flutter pub add shimmer`, oppure inserendolo manualmente nella sezione `dependencies` del file `pubspec.yaml`.\n\nDopo aver salvato, esegui `flutter pub get` per scaricare il pacchetto (il comando `pub add` lo fa già in automatico).","dependencies:\n  flutter:\n    sdk: flutter\n  shimmer: ^3.0.0","yaml","Il pacchetto shimmer è disponibile nel progetto e importabile con `import 'package:shimmer\u002Fshimmer.dart';`.",{"id":33,"position":34,"title":35,"body":36,"code_snippet":37,"code_language":38,"expected_result":39,"demo_url":10,"video_url":10},245,2,"Creare un modello dati e simulare il caricamento","Definiamo un semplice modello `Articolo` e una funzione che simula una chiamata di rete con un ritardo tramite `Future.delayed`. Questo ci permetterà di vedere l'effetto shimmer per qualche secondo prima di mostrare i dati reali.","class Articolo {\n  final String titolo;\n  final String descrizione;\n\n  Articolo({required this.titolo, required this.descrizione});\n}\n\nFuture\u003CList\u003CArticolo>> caricaArticoli() async {\n  \u002F\u002F Simula una chiamata di rete\n  await Future.delayed(const Duration(seconds: 3));\n  return List.generate(\n    8,\n    (i) => Articolo(\n      titolo: 'Articolo numero ${i + 1}',\n      descrizione: 'Questa è la descrizione dettagliata dell\\'articolo ${i + 1}.',\n    ),\n  );\n}","dart","Hai una sorgente dati asincrona che restituisce una lista di articoli dopo 3 secondi.",{"id":41,"position":42,"title":43,"body":44,"code_snippet":45,"code_language":38,"expected_result":46,"demo_url":10,"video_url":10},246,3,"Costruire il widget placeholder (skeleton)","Il segreto di un buon skeleton è riprodurre la **forma** del contenuto finale con blocchi grigi. Creiamo un widget `ArticoloSkeleton` che imita il layout di una card articolo: un blocco per il titolo e due blocchi più stretti per la descrizione.\n\nÈ importante che i placeholder abbiano un colore pieno (di solito bianco o grigio chiaro), perché sarà l'effetto shimmer a colorarli.","import 'package:flutter\u002Fmaterial.dart';\n\nclass ArticoloSkeleton extends StatelessWidget {\n  const ArticoloSkeleton({super.key});\n\n  Widget _box({double? width, double height = 14}) {\n    return Container(\n      width: width,\n      height: height,\n      decoration: BoxDecoration(\n        color: Colors.white,\n        borderRadius: BorderRadius.circular(4),\n      ),\n    );\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Card(\n      margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),\n      child: Padding(\n        padding: const EdgeInsets.all(16),\n        child: Column(\n          crossAxisAlignment: CrossAxisAlignment.start,\n          children: [\n            _box(width: 180, height: 18),\n            const SizedBox(height: 12),\n            _box(width: double.infinity),\n            const SizedBox(height: 8),\n            _box(width: 220),\n          ],\n        ),\n      ),\n    );\n  }\n}","Un widget riutilizzabile che riproduce la struttura di una card articolo con blocchi bianchi.",{"id":48,"position":49,"title":50,"body":51,"code_snippet":52,"code_language":38,"expected_result":53,"demo_url":10,"video_url":10},247,4,"Applicare l'effetto shimmer con Shimmer.fromColors","Ora avvolgiamo la lista di skeleton in un widget `Shimmer.fromColors`. Questo widget applica l'animazione di scorrimento della luce a tutti i figli.\n\nI due parametri chiave sono `baseColor` (il colore di base dei blocchi) e `highlightColor` (il colore della luce che scorre). Usiamo un `ListView` con un numero fisso di skeleton per riempire lo schermo.","import 'package:flutter\u002Fmaterial.dart';\nimport 'package:shimmer\u002Fshimmer.dart';\n\nclass ListaSkeleton extends StatelessWidget {\n  const ListaSkeleton({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return Shimmer.fromColors(\n      baseColor: Colors.grey.shade300,\n      highlightColor: Colors.grey.shade100,\n      child: ListView.builder(\n        physics: const NeverScrollableScrollPhysics(),\n        itemCount: 6,\n        itemBuilder: (context, index) => const ArticoloSkeleton(),\n      ),\n    );\n  }\n}","Una lista di card grigie con una luce che scorre orizzontalmente in modo continuo.",{"id":55,"position":56,"title":57,"body":58,"code_snippet":59,"code_language":38,"expected_result":60,"demo_url":10,"video_url":10},248,5,"Mettere tutto insieme con FutureBuilder","Infine colleghiamo il caricamento dati alla UI. Usiamo un `FutureBuilder` per mostrare lo skeleton (`ListaSkeleton`) mentre lo stato è `waiting`, e la lista reale quando i dati sono disponibili.\n\nNota come lo skeleton abbia esattamente lo stesso layout delle card finali: questo evita salti visivi (*layout shift*) quando i dati arrivano.","class SchermataArticoli extends StatefulWidget {\n  const SchermataArticoli({super.key});\n\n  @override\n  State\u003CSchermataArticoli> createState() => _SchermataArticoliState();\n}\n\nclass _SchermataArticoliState extends State\u003CSchermataArticoli> {\n  late Future\u003CList\u003CArticolo>> _future;\n\n  @override\n  void initState() {\n    super.initState();\n    _future = caricaArticoli();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('Articoli')),\n      body: FutureBuilder\u003CList\u003CArticolo>>(\n        future: _future,\n        builder: (context, snapshot) {\n          if (snapshot.connectionState == ConnectionState.waiting) {\n            return const ListaSkeleton();\n          }\n          if (snapshot.hasError) {\n            return Center(child: Text('Errore: ${snapshot.error}'));\n          }\n          final articoli = snapshot.data ?? [];\n          return ListView.builder(\n            itemCount: articoli.length,\n            itemBuilder: (context, index) {\n              final a = articoli[index];\n              return Card(\n                margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),\n                child: ListTile(\n                  title: Text(a.titolo),\n                  subtitle: Text(a.descrizione),\n                ),\n              );\n            },\n          );\n        },\n      ),\n    );\n  }\n}","All'apertura della schermata vedi lo skeleton animato per 3 secondi, poi appaiono le card con i dati reali senza sfarfallii.",{"id":62,"position":63,"title":64,"body":65,"code_snippet":66,"code_language":38,"expected_result":67,"demo_url":10,"video_url":10},249,6,"Personalizzare direzione e velocità dell'effetto","Il widget `Shimmer` permette di personalizzare la direzione dello scorrimento e la durata dell'animazione. Usa `direction` per cambiare l'asse (ad esempio `ShimmerDirection.rtl` per destra-sinistra) e `period` per rallentare o velocizzare l'effetto.\n\nRegola questi valori in base allo stile della tua app: un effetto più lento risulta più elegante, uno più rapido comunica maggiore reattività.","Shimmer.fromColors(\n  baseColor: Colors.grey.shade300,\n  highlightColor: Colors.grey.shade100,\n  direction: ShimmerDirection.ltr,\n  period: const Duration(milliseconds: 1500),\n  child: const ListaSkeleton(),\n)","L'animazione shimmer si adatta alla direzione e alla velocità desiderate, integrandosi con il design della tua app.",[],1785219608729]