[{"data":1,"prerenderedAt":76},["ShallowReactive",2],{"tutorial-gestione-dei-temi-in-flutter-con-themedata-e-dark-mode-dinamica":3,"comments-tutorial-gestione-dei-temi-in-flutter-con-themedata-e-dark-mode-dinamica":75},{"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},9,"Gestione dei temi in Flutter con ThemeData e dark mode dinamica","gestione-dei-temi-in-flutter-con-themedata-e-dark-mode-dinamica","Impara a creare temi chiaro e scuro in Flutter, a centralizzarli con ThemeData e a far cambiare il tema dinamicamente all'utente con un toggle.","# Temi e Dark Mode in Flutter\n\nUn'app moderna deve adattarsi alle preferenze dell'utente, offrendo sia una modalità chiara che una scura. Flutter rende tutto questo semplice grazie a `ThemeData`, `ColorScheme` e al widget `MaterialApp`.\n\nIn questo tutorial costruiremo un'app con un tema chiaro e uno scuro completamente personalizzati, e aggiungeremo un interruttore che permette all'utente di cambiare tema in tempo reale. Vedremo anche come seguire automaticamente l'impostazione di sistema.\n\nAl termine avrai una struttura pulita e riutilizzabile per la gestione dei temi nei tuoi progetti.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Ftutorials\u002Fe47b4064-77e9-49db-8e48-72e711dcdf13.jpg",null,"intermediate",35,"3.x","published","2026-06-13T04:30:47+00:00","Temi e Dark Mode in Flutter con ThemeData","Guida pratica per creare temi chiaro\u002Fscuro in Flutter con ThemeData e cambiare la dark mode dinamicamente tramite un toggle.",{"id":19,"name":20,"slug":21},1,"Guide","guide",{"id":19,"name":23},"Flutter Bot",[25,32,40,47,54,61,68],{"id":26,"position":19,"title":27,"body":28,"code_snippet":29,"code_language":30,"expected_result":31,"demo_url":10,"video_url":10},63,"Creare il progetto e capire il punto di partenza","Iniziamo creando un nuovo progetto Flutter. Il widget `MaterialApp` espone tre proprietà fondamentali per la gestione dei temi:\n\n- `theme`: il tema usato in modalità chiara\n- `darkTheme`: il tema usato in modalità scura\n- `themeMode`: decide quale dei due applicare (`light`, `dark` o `system`)\n\nQuando `themeMode` è impostato su `ThemeMode.system`, Flutter segue automaticamente le impostazioni del dispositivo.","flutter create temi_app\ncd temi_app","bash","Un progetto Flutter funzionante pronto per essere modificato.",{"id":33,"position":34,"title":35,"body":36,"code_snippet":37,"code_language":38,"expected_result":39,"demo_url":10,"video_url":10},64,2,"Definire i temi chiaro e scuro in un file dedicato","Per mantenere il codice ordinato, centralizziamo i temi in un file separato `lib\u002Fapp_theme.dart`. Usiamo `ColorScheme.fromSeed` che genera automaticamente una palette coerente a partire da un colore base, sia per il tema chiaro che per quello scuro.","import 'package:flutter\u002Fmaterial.dart';\n\nclass AppTheme {\n  static const Color _seedColor = Colors.indigo;\n\n  static ThemeData get light => ThemeData(\n        useMaterial3: true,\n        colorScheme: ColorScheme.fromSeed(\n          seedColor: _seedColor,\n          brightness: Brightness.light,\n        ),\n        appBarTheme: const AppBarTheme(centerTitle: true),\n      );\n\n  static ThemeData get dark => ThemeData(\n        useMaterial3: true,\n        colorScheme: ColorScheme.fromSeed(\n          seedColor: _seedColor,\n          brightness: Brightness.dark,\n        ),\n        appBarTheme: const AppBarTheme(centerTitle: true),\n      );\n}","dart","Due temi pronti all'uso, accessibili tramite AppTheme.light e AppTheme.dark.",{"id":41,"position":42,"title":43,"body":44,"code_snippet":45,"code_language":38,"expected_result":46,"demo_url":10,"video_url":10},65,3,"Creare un controller per gestire lo stato del tema","Per cambiare tema dinamicamente abbiamo bisogno di uno stato condiviso. Usiamo un `ChangeNotifier` semplice, senza pacchetti esterni, sfruttando `ValueNotifier` oppure una classe dedicata. Qui creiamo un `ThemeController` che memorizza il `ThemeMode` corrente e notifica i listener al cambiamento.","import 'package:flutter\u002Fmaterial.dart';\n\nclass ThemeController extends ChangeNotifier {\n  ThemeMode _themeMode = ThemeMode.system;\n\n  ThemeMode get themeMode => _themeMode;\n\n  bool get isDark => _themeMode == ThemeMode.dark;\n\n  void setMode(ThemeMode mode) {\n    _themeMode = mode;\n    notifyListeners();\n  }\n\n  void toggleDark(bool enabled) {\n    _themeMode = enabled ? ThemeMode.dark : ThemeMode.light;\n    notifyListeners();\n  }\n}","Un controller riutilizzabile che gestisce e notifica i cambi di tema.",{"id":48,"position":49,"title":50,"body":51,"code_snippet":52,"code_language":38,"expected_result":53,"demo_url":10,"video_url":10},66,4,"Collegare il controller a MaterialApp","Nel `main.dart` istanziamo il `ThemeController` e usiamo `AnimatedBuilder` (o `ListenableBuilder` da Flutter 3.10+) per ricostruire `MaterialApp` ogni volta che il tema cambia. Passiamo i temi definiti in precedenza alle proprietà `theme`, `darkTheme` e `themeMode`.","import 'package:flutter\u002Fmaterial.dart';\nimport 'app_theme.dart';\nimport 'theme_controller.dart';\nimport 'home_page.dart';\n\nfinal themeController = ThemeController();\n\nvoid main() => runApp(const MyApp());\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return ListenableBuilder(\n      listenable: themeController,\n      builder: (context, _) {\n        return MaterialApp(\n          title: 'Temi App',\n          theme: AppTheme.light,\n          darkTheme: AppTheme.dark,\n          themeMode: themeController.themeMode,\n          home: const HomePage(),\n        );\n      },\n    );\n  }\n}","L'app si avvia seguendo il tema di sistema e si aggiorna quando cambia il themeMode.",{"id":55,"position":56,"title":57,"body":58,"code_snippet":59,"code_language":38,"expected_result":60,"demo_url":10,"video_url":10},67,5,"Aggiungere il toggle per cambiare tema","Creiamo la `HomePage` con uno `SwitchListTile` per attivare la dark mode e un gruppo di scelte per selezionare la modalità (chiaro, scuro o sistema). I colori dei widget si adatteranno automaticamente perché usano il `ColorScheme` del tema attivo.","import 'package:flutter\u002Fmaterial.dart';\nimport 'main.dart';\n\nclass HomePage extends StatelessWidget {\n  const HomePage({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    final mode = themeController.themeMode;\n    return Scaffold(\n      appBar: AppBar(title: const Text('Gestione Temi')),\n      body: ListView(\n        padding: const EdgeInsets.all(16),\n        children: [\n          SwitchListTile(\n            title: const Text('Modalità scura'),\n            value: themeController.isDark,\n            onChanged: themeController.toggleDark,\n          ),\n          const Divider(),\n          RadioListTile\u003CThemeMode>(\n            title: const Text('Sistema'),\n            value: ThemeMode.system,\n            groupValue: mode,\n            onChanged: (v) => themeController.setMode(v!),\n          ),\n          RadioListTile\u003CThemeMode>(\n            title: const Text('Chiaro'),\n            value: ThemeMode.light,\n            groupValue: mode,\n            onChanged: (v) => themeController.setMode(v!),\n          ),\n          RadioListTile\u003CThemeMode>(\n            title: const Text('Scuro'),\n            value: ThemeMode.dark,\n            groupValue: mode,\n            onChanged: (v) => themeController.setMode(v!),\n          ),\n          const SizedBox(height: 24),\n          Card(\n            child: Padding(\n              padding: const EdgeInsets.all(16),\n              child: Text(\n                'Esempio di contenuto che cambia colore con il tema.',\n                style: Theme.of(context).textTheme.bodyLarge,\n              ),\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n}","Cambiando lo switch o la modalità l'intera interfaccia passa da chiaro a scuro istantaneamente.",{"id":62,"position":63,"title":64,"body":65,"code_snippet":66,"code_language":38,"expected_result":67,"demo_url":10,"video_url":10},68,6,"Personalizzare componenti con gli ThemeExtension","Per colori personalizzati che non rientrano nel `ColorScheme` standard (es. il colore di un badge \"successo\"), Flutter offre `ThemeExtension`. In questo modo eviti di scrivere colori hard-coded nei widget e mantieni coerenza tra tema chiaro e scuro.","@immutable\nclass CustomColors extends ThemeExtension\u003CCustomColors> {\n  final Color success;\n  const CustomColors({required this.success});\n\n  @override\n  CustomColors copyWith({Color? success}) =>\n      CustomColors(success: success ?? this.success);\n\n  @override\n  CustomColors lerp(ThemeExtension\u003CCustomColors>? other, double t) {\n    if (other is! CustomColors) return this;\n    return CustomColors(success: Color.lerp(success, other.success, t)!);\n  }\n}\n\n\u002F\u002F Uso nei temi:\n\u002F\u002F extensions: const [CustomColors(success: Colors.green)]\n\u002F\u002F extensions: const [CustomColors(success: Color(0xFF66BB6A))]\n\u002F\u002F\n\u002F\u002F Lettura in un widget:\nfinal custom = Theme.of(context).extension\u003CCustomColors>()!;","Puoi accedere a colori personalizzati coerenti col tema tramite Theme.of(context).extension\u003CCustomColors>().",{"id":69,"position":70,"title":71,"body":72,"code_snippet":73,"code_language":38,"expected_result":74,"demo_url":10,"video_url":10},69,7,"Rendere persistente la scelta dell'utente","Infine, salviamo la preferenza dell'utente così che venga ricordata al riavvio dell'app. Usiamo `shared_preferences` per memorizzare il `ThemeMode` selezionato e lo carichiamo all'avvio. Aggiungi la dipendenza con `flutter pub add shared_preferences`.","import 'package:shared_preferences\u002Fshared_preferences.dart';\nimport 'package:flutter\u002Fmaterial.dart';\n\nclass ThemeController extends ChangeNotifier {\n  ThemeMode _themeMode = ThemeMode.system;\n  ThemeMode get themeMode => _themeMode;\n  bool get isDark => _themeMode == ThemeMode.dark;\n\n  Future\u003Cvoid> load() async {\n    final prefs = await SharedPreferences.getInstance();\n    final index = prefs.getInt('themeMode') ?? ThemeMode.system.index;\n    _themeMode = ThemeMode.values[index];\n    notifyListeners();\n  }\n\n  Future\u003Cvoid> setMode(ThemeMode mode) async {\n    _themeMode = mode;\n    notifyListeners();\n    final prefs = await SharedPreferences.getInstance();\n    await prefs.setInt('themeMode', mode.index);\n  }\n\n  void toggleDark(bool enabled) =>\n      setMode(enabled ? ThemeMode.dark : ThemeMode.light);\n}\n\n\u002F\u002F In main():\n\u002F\u002F WidgetsFlutterBinding.ensureInitialized();\n\u002F\u002F await themeController.load();\n\u002F\u002F runApp(const MyApp());","Alla riapertura dell'app il tema scelto dall'utente viene ripristinato automaticamente.",[],1781333424869]