Theme e ThemeData — cosa sono, principi e configurazione degli stili

Autore: IT Sectr Pubblicato: 2026-07-03 Tempo di lettura: 8 min

Theme e ThemeData — i meccanismi centrali di tematizzazione in Flutter che consentono di definire colori, caratteri, margini e stili dei componenti a livello globale per l'intera applicazione. ThemeData è un oggetto di configurazione passato a MaterialApp tramite il parametro theme. Secondo la documentazione ufficiale di Flutter (2026), una corretta configurazione di ThemeData riduce il codice di stile duplicato del 70–80% e garantisce un aspetto visivo uniforme su tutti gli schermi. Il sistema di ereditarietà integrato consente di sovrascrivere il tema a livello di singoli widget tramite Theme.of(context).

Punti chiave

  • ThemeData — oggetto di configurazione con tavolozza colori, tipografia e stili dei componenti
  • Theme.of(context) — accesso al tema corrente da qualsiasi widget tramite BuildContext
  • Light/Dark — supporto integrato per tema chiaro e scuro tramite theme e darkTheme
  • Theme — widget che eredita il tema agli elementi figli e consente di sovrascriverlo
  • ColorScheme — insieme di colori armoniosi che genera stili per l'intero sistema Material

Cosa sono Theme e ThemeData

ThemeData è una classe che contiene la descrizione completa dello stile visivo di un'applicazione Material. Viene passata a MaterialApp tramite il parametro theme o darkTheme ed è ereditata da tutti i widget figli. Ogni widget Material Design utilizza ThemeData per ottenere i propri stili: colori dei pulsanti, dimensioni dell'AppBar, stili del testo, margini delle card e icone.

Al centro di ThemeData si trova ColorScheme, che definisce i colori primary, secondary, surface, error e altri. Da questi colori vengono automaticamente calcolati gli stati (hover, focus, pressed) per tutti i componenti Material. Ad esempio, ElevatedButton utilizza il colore primary per lo sfondo e onPrimary per il testo — senza configurazione aggiuntiva.

Il widget Theme è un InheritedWidget che propaga il tema verso il basso nell'albero dei widget. Qualsiasi widget può accedere al tema corrente tramite Theme.of(context) e può anche creare un nuovo tema basato su quello esistente con valori sovrascritti tramite Theme.copyWith o ThemeData.copyWith.

In sintesi: ThemeData è l'unica fonte di stili dell'applicazione. Inizia lo sviluppo definendo ThemeData — questo imposta il linguaggio visivo dell'intero progetto e previene stili sparsi su schermi diversi.

ColorScheme: la base della tavolozza colori

ColorScheme è l'elemento centrale della tematizzazione in Material 3. Sostituisce i deprecati primarySwatch e primaryColor, fornendo un set completo di colori per tutti gli stati e componenti.

ColorScheme contiene 12 colori principali: primary, onPrimary, secondary, onSecondary, surface, onSurface, error, onError, background, onBackground, outline e shadow. Per ogni colore vengono automaticamente calcolate le varianti chiara e scura, nonché i colori per gli stati hover, focus, pressed e dragged. Quando viene specificato solo primary, il framework genera automaticamente i colori rimanenti tramite ColorScheme.fromSeed.

Il metodo ColorScheme.fromSeed (Material 3) prende un colore di base seedColor e genera una tavolozza armoniosa completa basata sull'algoritmo di Material Design 3. Ciò elimina la necessità di selezionare manualmente colori complementari e analoghi. Basta passare un colore primario del marchio, e ColorScheme.fromSeed crea una tavolozza coerente per l'intero sistema Material.

In sintesi: nei nuovi progetti, utilizza ColorScheme.fromSeed per generare la tavolozza. Per la compatibilità con Material 2 — usa primarySwatch. ColorScheme è il minimo richiesto per Material 3.

Tipografia e TextTheme: caratteri dell'applicazione

TextTheme è una parte di ThemeData che definisce gli stili del testo per tutti i livelli di intestazioni, sottotitoli, corpo ed etichette. Material Design definisce 15 stili di testo: headlineLarge, headlineMedium, headlineSmall, titleLarge, titleMedium e altri.

La tipografia viene impostata tramite GoogleFonts per il caricamento automatico dei caratteri, oppure tramite il Theme.of(context).textTheme integrato con oggetti TextStyle personalizzati. GoogleFonts fornisce centinaia di caratteri tramite il pacchetto google_fonts, che li memorizza nella cache locale dopo il primo caricamento. L'alternativa è incorporare i caratteri negli asset del progetto tramite pubspec.yaml.

Per una tipografia adattiva, TextTheme supporta MediaQuery.textScaleFactor — quando la dimensione del carattere di sistema aumenta, tutti gli stili del testo vengono ridimensionati proporzionalmente. Inoltre, è possibile impostare diverse dimensioni dei caratteri per diversi fattori di forma tramite isTest in base a MediaQuery.size.width.

In sintesi: definisci TextTheme in ThemeData e utilizza Theme.of(context).textTheme per tutti gli elementi di testo. Ciò garantisce la coerenza dei caratteri e semplifica le modifiche globali alla tipografia.

Ereditarietà e sovrascrittura del tema

Theme è un InheritedWidget che propaga il tema dai genitori ai figli. Qualsiasi widget figlio può sia leggere il tema corrente tramite Theme.of(context) sia creare la propria copia con modifiche tramite ThemeData.copyWith.

Meccanismo di ereditarietà: se un widget è avvolto in un Theme con nuovi dati, tutti i suoi discendenti vedono il tema sovrascritto, mentre i widget al di fuori di questo involucro vedono l'originale. Ciò consente, ad esempio, di isolare gli stili per uno schermo specifico: un'intestazione utilizza un tema personalizzato con un AppBarTheme modificato, mentre il resto dell'applicazione utilizza quello standard.

L'annidamento di Theme può essere illimitato. Flutter utilizza una ricerca gerarchica: quando si chiama Theme.of(context), il framework risale l'albero fino al primo Theme e restituisce il suo tema. Se non viene trovato alcun Theme — viene lanciata un'eccezione. Pertanto, MaterialApp avvolge sempre l'applicazione in un Theme.

In sintesi: l'ereditarietà di Theme è un meccanismo flessibile per isolare gli stili. Utilizza la sovrascrittura del tema per schermi individuali senza duplicare la configurazione globale.

Tema scuro: modalità scura dell'applicazione

Tema scuro è la capacità integrata di Flutter di passare tra tema chiaro e scuro. ThemeData viene memorizzato nei parametri theme (chiaro) e darkTheme (scuro) di MaterialApp. Il parametro themeMode controlla la modalità: ThemeMode.light (sempre chiaro), ThemeMode.dark (sempre scuro) o ThemeMode.system (segue le impostazioni di sistema).

Nell'implementare un tema scuro, non è necessario ricreare tutti gli stili da zero. Basta passare ColorScheme.fromSeed(seedColor, brightness: Brightness.dark) a darkTheme. Il framework regolerà automaticamente i colori per uno sfondo scuro: surface diventa grigio scuro, il testo diventa chiaro. Altri sottotemi (AppBarTheme, CardTheme, BottomNavigationBarTheme) vengono ereditati dalla versione chiara a meno che non vengano esplicitamente sovrascritti.

Per transizioni fluide tra i temi, Flutter fornisce animazione tramite AnimatedTheme. Quando themeMode cambia, i colori e gli stili si animano, creando una transizione visivamente piacevole. AnimatedTheme utilizza Duration e Curve per configurare la velocità dell'animazione.

In sintesi: il tema scuro viene implementato tramite darkTheme e ColorScheme.fromSeed con brightness: Brightness.dark. Utilizza ThemeMode.system per seguire le impostazioni di sistema dell'utente.

Esempi di codice con Theme e ThemeData

Esempio 1 — configurazione globale del tema tramite MaterialApp usando ColorScheme.fromSeed.

dart
final ThemeData appTheme = ThemeData(
  useMaterial3: true,
  colorScheme: ColorScheme.fromSeed(
    seedColor: Colors.indigo,
    brightness: Brightness.light,
  ),
  appBarTheme: const AppBarTheme(
    centerTitle: true,
    elevation: 0,
  ),
  cardTheme: const CardTheme(
    elevation: 2,
    margin: EdgeInsets.all(8),
  ),
);

return MaterialApp(
  theme: appTheme,
  themeMode: ThemeMode.system,
  home: const MyHomePage(),
);

Questo esempio crea un ThemeData con Material 3, una combinazione di colori basata sull'indaco e stili personalizzati di AppBar e Card. useMaterial3 abilita il nuovo sistema di tematizzazione Material 3, e ColorScheme.fromSeed genera la tavolozza completa.

Esempio 2 — accesso al tema e sovrascrittura per una parte dell'applicazione.

dart
Widget build(BuildContext context) {
  final theme = Theme.of(context);

  return Column(
    children: [
      Text(
        'Standard headline',
        style: theme.textTheme.headlineMedium,
      ),
      Theme(
        data: theme.copyWith(
          colorScheme: theme.colorScheme.copyWith(
            primary: Colors.orange,
          ),
        ),
        child: const SpecialSection(),
      ),
    ],
  );
}

Il secondo esempio dimostra l'uso di Theme.of(context) per leggere gli stili e Theme() con copyWith per sovrascrivere il tema in una parte dell'albero senza modificare la configurazione globale. SpecialSection all'interno di Theme riceverà il colore primary arancione, mentre il resto dell'applicazione mantiene l'indaco originale.

In sintesi: il tema globale viene impostato in MaterialApp, accessibile tramite Theme.of(context) e sovrascritto tramite Theme con copyWith. Per Material 3, utilizza ColorScheme.fromSeed.

Errori comuni nella configurazione del tema

Errore 1: usare primarySwatch invece di ColorScheme in Material 3. primarySwatch è deprecato e non supportato in Material 3. Quando si usa useMaterial3: true con primarySwatch, Flutter emette un avviso. Soluzione: passare a ColorScheme.fromSeed per la generazione della tavolozza.

Errore 2: codificare direttamente i colori nei widget invece di usare Theme.of(context). Gli sviluppatori scrivono Colors.blue direttamente in un Container invece del colore primary o secondary del tema. Quando il tema cambia, questi colori rimangono invariati, rompendo la coerenza dello stile. Soluzione: usa sempre Theme.of(context).colorScheme.primary o altri colori del tema.

Errore 3: mancanza di darkTheme. Se l'applicazione non definisce darkTheme, quando il tema scuro viene attivato sul dispositivo, Flutter tenta di adattare automaticamente il tema chiaro, spesso con un risultato di bassa qualità. Soluzione: passa sempre darkTheme a MaterialApp, anche se il tema scuro non è una priorità — questa è un'importante UX per gli utenti.

Errore 4: creare un nuovo tema ad ogni build. Se ThemeData viene creato all'interno del metodo build, ogni ricostruzione del widget crea un nuovo oggetto tema, rompendo l'ottimizzazione di InheritedWidget. Soluzione: sposta ThemeData in un campo static o costruttore const al di fuori di build.

In sintesi: una corretta tematizzazione richiede un approccio centralizzato. Sposta ThemeData in costanti, usa gli schemi di colore dal tema e definisci sempre entrambi i temi — chiaro e scuro.

Domande frequenti

Qual è la differenza tra Theme e ThemeData?

ThemeData sono i dati di configurazione (colori, caratteri, stili). Theme è un InheritedWidget che trasmette ThemeData verso il basso nell'albero dei widget. Theme.of(context) restituisce il ThemeData che il Theme più vicino propaga nel contesto corrente.

Come cambiare dinamicamente il tema dell'applicazione?

Controlla themeMode in MaterialApp tramite lo stato dell'applicazione. Cambia lo stato da ThemeMode.light a ThemeMode.dark, e Flutter ricostruirà l'intero albero con il nuovo tema. Per un'animazione fluida, usa AnimatedTheme.

Cos'è ColorScheme.fromSeed?

ColorScheme.fromSeed è un metodo di Material 3 che prende un colore di base (seedColor) e genera una tavolozza armoniosa completa: primary, secondary, tertiary, surface, error e le loro varianti on. Permette di ottenere una combinazione di colori coerente da un singolo colore del marchio.

Come usare caratteri personalizzati con Theme?

Tramite TextTheme all'interno di ThemeData: specifica TextStyle con fontFamily per ogni livello. Per Google Fonts, usa il pacchetto google_fonts, passando fontFamily direttamente a TextTheme. Per i caratteri locali — includili tramite pubspec.yaml nella sezione fonts.

Si può sovrascrivere il tema per un singolo schermo?

. Avvolgi lo schermo in un Theme con dati sovrascritti tramite copyWith. Tutti i widget figli all'interno di questo Theme riceveranno gli stili modificati, mentre il resto dell'applicazione mantiene il tema originale. Ciò non crea overhead aggiuntivo.

Riepilogo

  • ThemeData — oggetto di configurazione con tavolozza colori, tipografia e stili di tutti i componenti Material
  • ColorScheme.fromSeed — il modo principale per generare una tavolozza di colori in Material 3 da un singolo colore del marchio
  • Theme.of(context) — accesso al tema corrente per leggere gli stili senza duplicazione di codice
  • Theme — InheritedWidget per ereditare e sovrascrivere il tema in un sottoalbero di widget
  • Tema scuro — ThemeData separato con brightness: Brightness.dark, controllato tramite themeMode
  • Raccomandazione: sposta ThemeData in static o const, definisci sempre theme e darkTheme in MaterialApp

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche