[{"data":1,"prerenderedAt":86},["ShallowReactive",2],{"tutorial-tipografia-in-flutter-textstyle-texttheme-e-google-fonts":3,"comments-tutorial-tipografia-in-flutter-textstyle-texttheme-e-google-fonts":85},{"id":4,"title":5,"slug":6,"excerpt":7,"intro":8,"cover_image":9,"cover_remote_url":10,"cover_credit":11,"video_url":15,"video":16,"difficulty":20,"estimated_minutes":21,"flutter_version":22,"status":23,"published_at":24,"meta_title":25,"meta_description":26,"category":27,"author":31,"steps":33},120,"Tipografia in Flutter: TextStyle, TextTheme e google_fonts","tipografia-in-flutter-textstyle-texttheme-e-google-fonts","Impara a gestire i testi della tua app Flutter: dalle proprietà di TextStyle alla scala tipografica di TextTheme, fino ai font personalizzati con google_fonts e agli asset locali.","La tipografia è uno degli elementi che distingue un'app curata da una raffazzonata. In Flutter tutto il testo passa dal widget `Text` e dalla classe `TextStyle`, ma scrivere stili a mano in ogni schermata porta rapidamente a incoerenze: titoli di dimensioni diverse, pesi sbagliati, colori che non rispettano il tema.\n\nIn questa guida per principianti vedremo come:\n\n- usare `TextStyle` e le sue proprietà principali (`fontSize`, `fontWeight`, `letterSpacing`, `height`);\n- applicare font di Google con il pacchetto **google_fonts**;\n- centralizzare la tipografia dell'app con `TextTheme` dentro `ThemeData`;\n- richiamare gli stili con `Theme.of(context).textTheme`;\n- includere i font come asset locali per funzionare anche offline;\n- rispettare le impostazioni di accessibilità dell'utente.\n\nAlla fine avrai una piccola app con una scala tipografica coerente e riutilizzabile in tutte le schermate.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Ftutorials\u002Feb575706-3959-45c3-bc3f-62622bc3ac97.jpg","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1552333331-6bb4a9c1e62a?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w5NzA2NTJ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3OTE2MDY2ODd8&ixlib=rb-4.1.0&q=80&w=1080",{"name":12,"author_url":13,"photo_url":14},"Patrick Fore","https:\u002F\u002Funsplash.com\u002F@patrickian4","https:\u002F\u002Funsplash.com\u002Fphotos\u002Fbrown-letters-decors-Rm5dTBSwzaY","https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=pUdjBRkRqmI",{"youtube_id":17,"duration_seconds":18,"published_at":19},"pUdjBRkRqmI",146,"2026-10-10T10:55:30+00:00","beginner",35,"3.x","published","2026-10-10T04:31:27+00:00","Tipografia in Flutter: TextStyle e google_fonts","Guida beginner alla tipografia in Flutter: TextStyle, TextTheme in ThemeData, font con google_fonts, asset locali e accessibilità del testo.",{"id":28,"name":29,"slug":30},1,"Guide","guide",{"id":28,"name":32},"Flutter Bot",[34,42,49,56,63,70,78],{"id":35,"position":28,"title":36,"body":37,"code_snippet":38,"code_language":39,"expected_result":40,"demo_url":41,"video_url":41},802,"Creare il progetto e aggiungere google_fonts","Partiamo da un progetto nuovo e aggiungiamo il pacchetto [google_fonts](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fgoogle_fonts), che permette di usare oltre mille font gratuiti senza scaricarli manualmente.\n\n```bash\nflutter create tipografia_demo\ncd tipografia_demo\nflutter pub add google_fonts\n```\n\nIl comando `flutter pub add` aggiorna automaticamente il `pubspec.yaml` ed esegue `flutter pub get`.\n\n> **Come funziona google_fonts?** Alla prima esecuzione il pacchetto scarica il font da fonts.google.com e lo mette in cache sul dispositivo. Serve quindi la connessione al primo avvio: nell'ultimo passo vedremo come evitarlo includendo i font come asset.\n\nSvuotiamo poi `lib\u002Fmain.dart` e scriviamo uno scheletro minimo su cui lavorare.","import 'package:flutter\u002Fmaterial.dart';\n\nvoid main() => runApp(const TipografiaApp());\n\nclass TipografiaApp extends StatelessWidget {\n  const TipografiaApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: 'Tipografia Demo',\n      debugShowCheckedModeBanner: false,\n      home: const HomePage(),\n    );\n  }\n}\n\nclass HomePage extends StatelessWidget {\n  const HomePage({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('Tipografia')),\n      body: const Center(child: Text('Ciao Flutter!')),\n    );\n  }\n}","dart","L'app si avvia mostrando una AppBar con il titolo \"Tipografia\" e il testo \"Ciao Flutter!\" al centro, con il font di sistema.",null,{"id":43,"position":44,"title":45,"body":46,"code_snippet":47,"code_language":39,"expected_result":48,"demo_url":41,"video_url":41},803,2,"Le proprietà fondamentali di TextStyle","Il widget `Text` accetta un parametro `style` di tipo `TextStyle`. Le proprietà che userai praticamente sempre sono:\n\n| Proprietà | A cosa serve |\n|---|---|\n| `fontSize` | Dimensione in *logical pixel* |\n| `fontWeight` | Spessore del tratto (`w400` = normale, `w700` = bold) |\n| `color` | Colore del testo |\n| `letterSpacing` | Spaziatura tra le lettere (anche negativa) |\n| `height` | Interlinea come **moltiplicatore** di `fontSize` (1.4 = 140%) |\n| `fontStyle` | `FontStyle.italic` per il corsivo |\n| `decoration` | Sottolineato, barrato, ecc. |\n\nDue consigli pratici fin da subito:\n\n- usa `maxLines` + `overflow: TextOverflow.ellipsis` sui testi che possono essere lunghi, per evitare gli overflow;\n- `height` è un moltiplicatore, non un valore in pixel: per un paragrafo leggibile punta a 1.4–1.6.\n\nSostituiamo il body della `HomePage` con alcuni esempi.","class HomePage extends StatelessWidget {\n  const HomePage({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('Tipografia')),\n      body: Padding(\n        padding: const EdgeInsets.all(24),\n        child: Column(\n          crossAxisAlignment: CrossAxisAlignment.start,\n          children: [\n            const Text(\n              'Titolo in evidenza',\n              style: TextStyle(\n                fontSize: 28,\n                fontWeight: FontWeight.w700,\n                letterSpacing: -0.5,\n              ),\n            ),\n            const SizedBox(height: 8),\n            Text(\n              'Sottotitolo descrittivo',\n              style: TextStyle(\n                fontSize: 16,\n                fontWeight: FontWeight.w500,\n                color: Colors.grey.shade600,\n              ),\n            ),\n            const SizedBox(height: 16),\n            const Text(\n              'Questo è un paragrafo di esempio che mostra come l\\'interlinea '\n              'renda il testo molto più leggibile su più righe.',\n              style: TextStyle(fontSize: 15, height: 1.5),\n            ),\n            const SizedBox(height: 16),\n            const Text(\n              'Un titolo molto lungo che non deve mandare in overflow il layout',\n              maxLines: 1,\n              overflow: TextOverflow.ellipsis,\n              style: TextStyle(fontSize: 18, fontStyle: FontStyle.italic),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}","La schermata mostra quattro testi con dimensioni, pesi e interlinee diverse; l'ultimo viene troncato con i tre puntini invece di uscire dallo schermo.",{"id":50,"position":51,"title":52,"body":53,"code_snippet":54,"code_language":39,"expected_result":55,"demo_url":41,"video_url":41},804,3,"Applicare un font di Google a un singolo testo","Il pacchetto `google_fonts` espone un metodo statico per ogni famiglia di font. Ad esempio `GoogleFonts.poppins()` restituisce un `TextStyle` già configurato con quella famiglia.\n\nPuoi passare le stesse proprietà di `TextStyle` direttamente al metodo:\n\n```dart\nGoogleFonts.poppins(fontSize: 24, fontWeight: FontWeight.w600)\n```\n\nOppure partire da uno stile esistente e cambiarne solo la famiglia con il parametro `textStyle`:\n\n```dart\nGoogleFonts.poppins(textStyle: const TextStyle(fontSize: 24))\n```\n\n> **Attenzione ai nomi:** il metodo segue il nome del font in *lowerCamelCase*: `Roboto Mono` diventa `GoogleFonts.robotoMono()`, `Playfair Display` diventa `GoogleFonts.playfairDisplay()`.\n\nProviamo a confrontare tre font diversi nella stessa schermata.","import 'package:flutter\u002Fmaterial.dart';\nimport 'package:google_fonts\u002Fgoogle_fonts.dart';\n\nclass FontDemo extends StatelessWidget {\n  const FontDemo({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    const frase = 'Flutter rende la UI divertente';\n\n    return Padding(\n      padding: const EdgeInsets.all(24),\n      child: Column(\n        crossAxisAlignment: CrossAxisAlignment.start,\n        children: [\n          Text(frase, style: GoogleFonts.poppins(fontSize: 22, fontWeight: FontWeight.w600)),\n          const SizedBox(height: 16),\n          Text(frase, style: GoogleFonts.playfairDisplay(fontSize: 22, fontStyle: FontStyle.italic)),\n          const SizedBox(height: 16),\n          Text(frase, style: GoogleFonts.robotoMono(fontSize: 18, letterSpacing: 0.5)),\n        ],\n      ),\n    );\n  }\n}","Le tre frasi vengono renderizzate con font chiaramente diversi (sans-serif geometrico, serif corsivo e monospace).",{"id":57,"position":58,"title":59,"body":60,"code_snippet":61,"code_language":39,"expected_result":62,"demo_url":41,"video_url":41},805,4,"Centralizzare la tipografia con TextTheme in ThemeData","Scrivere gli stili dentro ogni widget non scala: se domani cambi font, devi toccare decine di file. La soluzione è definire la **scala tipografica** una sola volta dentro `ThemeData.textTheme`.\n\nMaterial 3 definisce 15 stili raggruppati in cinque famiglie, dal più grande al più piccolo:\n\n- `displayLarge\u002FMedium\u002FSmall` – numeri e testi molto grandi (usali con parsimonia);\n- `headlineLarge\u002FMedium\u002FSmall` – titoli di schermata;\n- `titleLarge\u002FMedium\u002FSmall` – titoli di card e sezioni;\n- `bodyLarge\u002FMedium\u002FSmall` – testo di contenuto (`bodyMedium` è il default);\n- `labelLarge\u002FMedium\u002FSmall` – etichette di bottoni e chip.\n\n`google_fonts` offre una scorciatoia comodissima: `GoogleFonts.poppinsTextTheme()` restituisce un `TextTheme` completo in cui tutti e 15 gli stili usano quel font. Puoi poi sovrascrivere i singoli stili con `copyWith`.\n\nUn pattern molto usato è combinare due font: uno per i titoli, uno per il corpo del testo.","import 'package:flutter\u002Fmaterial.dart';\nimport 'package:google_fonts\u002Fgoogle_fonts.dart';\n\nclass TipografiaApp extends StatelessWidget {\n  const TipografiaApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    \u002F\u002F Scala base basata su Inter per il corpo del testo...\n    final base = GoogleFonts.interTextTheme();\n\n    \u002F\u002F ...e Poppins per i titoli.\n    final textTheme = base.copyWith(\n      headlineMedium: GoogleFonts.poppins(\n        fontSize: 28,\n        fontWeight: FontWeight.w700,\n        letterSpacing: -0.5,\n      ),\n      titleMedium: GoogleFonts.poppins(\n        fontSize: 18,\n        fontWeight: FontWeight.w600,\n      ),\n      bodyMedium: base.bodyMedium?.copyWith(fontSize: 15, height: 1.5),\n      labelLarge: GoogleFonts.poppins(\n        fontSize: 14,\n        fontWeight: FontWeight.w600,\n      ),\n    );\n\n    return MaterialApp(\n      title: 'Tipografia Demo',\n      debugShowCheckedModeBanner: false,\n      theme: ThemeData(\n        useMaterial3: true,\n        colorSchemeSeed: const Color(0xFF3F51B5),\n        textTheme: textTheme,\n      ),\n      home: const HomePage(),\n    );\n  }\n}","Dopo l'hot restart tutti i testi dell'app (compresi quelli dei bottoni e della AppBar) usano i nuovi font, senza aver modificato i singoli widget.",{"id":64,"position":65,"title":66,"body":67,"code_snippet":68,"code_language":39,"expected_result":69,"demo_url":41,"video_url":41},806,5,"Usare gli stili del tema nei widget","Ora che la scala è definita, nei widget non devi più scrivere `fontSize` a mano: basta leggere lo stile dal tema con `Theme.of(context).textTheme`.\n\n```dart\nText('Titolo', style: Theme.of(context).textTheme.headlineMedium)\n```\n\nSe ti serve una piccola variazione (ad esempio il colore), usa `copyWith` **sullo stile del tema**, così mantieni font e dimensioni coerenti:\n\n```dart\nstyle: Theme.of(context).textTheme.bodyMedium?.copyWith(\n  color: Theme.of(context).colorScheme.primary,\n)\n```\n\nPer risparmiare righe, salva `final text = Theme.of(context).textTheme;` all'inizio del metodo `build`. Riscriviamo la home usando solo stili del tema.","class HomePage extends StatelessWidget {\n  const HomePage({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    final text = Theme.of(context).textTheme;\n    final colors = Theme.of(context).colorScheme;\n\n    return Scaffold(\n      appBar: AppBar(title: const Text('Tipografia')),\n      body: ListView(\n        padding: const EdgeInsets.all(24),\n        children: [\n          Text('Benvenuto in Flutter', style: text.headlineMedium),\n          const SizedBox(height: 4),\n          Text(\n            'Guida alla tipografia',\n            style: text.titleMedium?.copyWith(color: colors.primary),\n          ),\n          const SizedBox(height: 16),\n          Text(\n            'Usando TextTheme definisci gli stili una sola volta e li riusi '\n            'in tutta l\\'app. Cambiare font diventa una modifica di una riga.',\n            style: text.bodyMedium,\n          ),\n          const SizedBox(height: 24),\n          Card(\n            child: Padding(\n              padding: const EdgeInsets.all(16),\n              child: Column(\n                crossAxisAlignment: CrossAxisAlignment.start,\n                children: [\n                  Text('Card di esempio', style: text.titleMedium),\n                  const SizedBox(height: 8),\n                  Text('Contenuto secondario della card.', style: text.bodySmall),\n                ],\n              ),\n            ),\n          ),\n          const SizedBox(height: 24),\n          FilledButton(\n            onPressed: () {},\n            child: const Text('Continua'),\n          ),\n        ],\n      ),\n    );\n  }\n}","La schermata mostra una gerarchia visiva chiara (titolo, sottotitolo colorato, paragrafo, card e bottone) con un solo punto di configurazione per i font.",{"id":71,"position":72,"title":73,"body":74,"code_snippet":75,"code_language":76,"expected_result":77,"demo_url":41,"video_url":41},807,6,"Font come asset locali: niente download a runtime","Scaricare i font a runtime va bene in sviluppo, ma in produzione significa dipendere dalla rete al primo avvio (e sul web può causare un lampo di testo con il font sbagliato). La soluzione è includere i file `.ttf` nel bundle dell'app.\n\n1. Scarica la famiglia da [fonts.google.com](https:\u002F\u002Ffonts.google.com) e copia i file in `assets\u002Ffonts\u002F`.\n2. Dichiarali nel `pubspec.yaml` rispettando l'indentazione (2 spazi, mai tabulazioni).\n3. Disattiva il download a runtime impostando `GoogleFonts.config.allowRuntimeFetching = false;` nel `main`: se un font non è tra gli asset, Flutter userà il fallback invece di scaricarlo.\n\nDopo aver modificato il `pubspec.yaml` serve un **full restart** (non basta l'hot reload) perché gli asset vengano ricaricati.\n\nSe preferisci non usare `google_fonts`, puoi anche riferirti al font direttamente con `fontFamily: 'Poppins'` in un `TextStyle`: il nome deve corrispondere alla chiave `family` del pubspec.","# pubspec.yaml\nflutter:\n  uses-material-design: true\n  fonts:\n    - family: Poppins\n      fonts:\n        - asset: assets\u002Ffonts\u002FPoppins-Regular.ttf\n          weight: 400\n        - asset: assets\u002Ffonts\u002FPoppins-SemiBold.ttf\n          weight: 600\n        - asset: assets\u002Ffonts\u002FPoppins-Bold.ttf\n          weight: 700\n\n# --- lib\u002Fmain.dart ---\n# void main() {\n#   WidgetsFlutterBinding.ensureInitialized();\n#   GoogleFonts.config.allowRuntimeFetching = false;\n#   runApp(const TipografiaApp());\n# }\n#\n# Uso senza google_fonts:\n# Text('Ciao', style: TextStyle(fontFamily: 'Poppins', fontWeight: FontWeight.w600))","yaml","L'app mostra i font corretti anche in modalità aereo, senza alcun download al primo avvio.",{"id":79,"position":80,"title":81,"body":82,"code_snippet":83,"code_language":39,"expected_result":84,"demo_url":41,"video_url":41},808,7,"Rispettare l'accessibilità: dimensioni del testo scalabili","Gli utenti possono ingrandire il testo dalle impostazioni di sistema. Flutter lo gestisce automaticamente tramite il `TextScaler`: le tue `fontSize` vengono moltiplicate. Per questo è importante:\n\n- **non bloccare mai** lo scaling con `TextScaler.noScaling` su tutta l'app;\n- evitare altezze fisse sui contenitori di testo: preferisci `Padding` + contenuto che cresce;\n- usare `maxLines` e `overflow` dove serve, ma lasciando spazio sufficiente.\n\nSe vuoi evitare che testi enormi distruggano il layout, puoi **limitare** il fattore di scala con `TextScaler.linear(...).clamp(...)` mantenendo comunque l'accessibilità. Ecco come applicarlo globalmente tramite il `builder` di `MaterialApp`.\n\nPer testare: su Android vai in *Impostazioni → Display → Dimensioni carattere*, su iOS in *Accessibilità → Testo più grande*. In alternativa usa il pannello **Accessibility** dei Flutter DevTools.","return MaterialApp(\n  theme: ThemeData(useMaterial3: true, textTheme: textTheme),\n  builder: (context, child) {\n    final scaler = MediaQuery.textScalerOf(context).clamp(\n      minScaleFactor: 0.9,\n      maxScaleFactor: 1.5,\n    );\n    return MediaQuery.withClampedTextScaling(\n      minScaleFactor: 0.9,\n      maxScaleFactor: 1.5,\n      child: child!,\n    );\n    \u002F\u002F Nota: `scaler` qui sopra mostra l'API equivalente di basso livello,\n    \u002F\u002F withClampedTextScaling è la via più semplice e consigliata.\n  },\n  home: const HomePage(),\n);","Aumentando la dimensione del carattere nelle impostazioni di sistema i testi dell'app crescono, ma senza superare il 150% e senza rompere il layout.",[],1792316904552]