[{"data":1,"prerenderedAt":74},["ShallowReactive",2],{"tutorial-creare-layout-responsive-in-flutter-con-layoutbuilder-e-mediaquery":3,"comments-tutorial-creare-layout-responsive-in-flutter-con-layoutbuilder-e-mediaquery":73},{"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},8,"Creare layout responsive in Flutter con LayoutBuilder e MediaQuery","creare-layout-responsive-in-flutter-con-layoutbuilder-e-mediaquery","Impara a costruire interfacce Flutter che si adattano a smartphone, tablet e desktop usando LayoutBuilder, MediaQuery e widget responsive.","Le app Flutter possono girare su dispositivi con dimensioni dello schermo molto diverse: telefoni, tablet, web e desktop. Per offrire una buona esperienza utente è fondamentale costruire layout **responsive** che si adattino allo spazio disponibile.\n\nIn questo tutorial vedremo come usare `MediaQuery` per leggere le dimensioni dello schermo, `LayoutBuilder` per reagire ai vincoli del contenitore e widget come `Flexible`, `Expanded` e `Wrap` per costruire interfacce adattive. Realizzeremo una schermata che mostra una griglia di card che cambia layout in base alla larghezza disponibile.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Ftutorials\u002F9c2011b5-e544-429b-bfda-78dfed092f9c.jpg",null,"intermediate",35,"3.x","published","2026-06-12T04:30:49+00:00","Layout responsive in Flutter con LayoutBuilder","Guida pratica per creare interfacce Flutter responsive e adattive con LayoutBuilder, MediaQuery e widget come Wrap ed Expanded.",{"id":19,"name":20,"slug":21},1,"Guide","guide",{"id":19,"name":23},"Flutter Bot",[25,32,39,46,53,60,67],{"id":26,"position":19,"title":27,"body":28,"code_snippet":29,"code_language":30,"expected_result":31,"demo_url":10,"video_url":10},56,"Comprendere MediaQuery e LayoutBuilder","Prima di scrivere codice è importante capire la differenza tra i due strumenti principali:\n\n- **`MediaQuery`**: fornisce informazioni sull'intero schermo (dimensioni, orientamento, padding di sistema, scala del testo). È utile per decisioni globali.\n- **`LayoutBuilder`**: fornisce i **vincoli** (constraints) dello spazio in cui un widget viene effettivamente posizionato. È perfetto quando un widget potrebbe non occupare tutto lo schermo (es. dentro una colonna o un pannello laterale).\n\nIn generale: usa `MediaQuery` per scelte di alto livello e `LayoutBuilder` per adattamenti locali.","\u002F\u002F Lettura delle dimensioni dello schermo\nfinal size = MediaQuery.of(context).size;\nfinal larghezza = size.width;\nfinal orientamento = MediaQuery.of(context).orientation;\n\nprint('Larghezza schermo: $larghezza');\nprint('Orientamento: $orientamento');","dart","Hai chiaro quando usare MediaQuery e quando LayoutBuilder.",{"id":33,"position":34,"title":35,"body":36,"code_snippet":37,"code_language":30,"expected_result":38,"demo_url":10,"video_url":10},57,2,"Definire i breakpoint dell'app","Per gestire diversi tipi di dispositivi conviene definire dei **breakpoint** centralizzati. Creiamo una classe di utilità con soglie standard per mobile, tablet e desktop, così da evitare di ripetere numeri magici nel codice.","class Breakpoints {\n  static const double mobile = 600;\n  static const double tablet = 1024;\n}\n\nenum TipoDispositivo { mobile, tablet, desktop }\n\nTipoDispositivo tipoDispositivo(double larghezza) {\n  if (larghezza \u003C Breakpoints.mobile) return TipoDispositivo.mobile;\n  if (larghezza \u003C Breakpoints.tablet) return TipoDispositivo.tablet;\n  return TipoDispositivo.desktop;\n}","Hai una funzione riutilizzabile che classifica il dispositivo in base alla larghezza.",{"id":40,"position":41,"title":42,"body":43,"code_snippet":44,"code_language":30,"expected_result":45,"demo_url":10,"video_url":10},58,3,"Creare un widget responsive con LayoutBuilder","Costruiamo un widget `LayoutResponsivo` che mostra contenuti diversi in base ai vincoli ricevuti. Usiamo `LayoutBuilder` perché reagisce allo spazio reale assegnato al widget, non all'intero schermo.","import 'package:flutter\u002Fmaterial.dart';\n\nclass LayoutResponsivo extends StatelessWidget {\n  final Widget mobile;\n  final Widget tablet;\n  final Widget desktop;\n\n  const LayoutResponsivo({\n    super.key,\n    required this.mobile,\n    required this.tablet,\n    required this.desktop,\n  });\n\n  @override\n  Widget build(BuildContext context) {\n    return LayoutBuilder(\n      builder: (context, constraints) {\n        final tipo = tipoDispositivo(constraints.maxWidth);\n        switch (tipo) {\n          case TipoDispositivo.mobile:\n            return mobile;\n          case TipoDispositivo.tablet:\n            return tablet;\n          case TipoDispositivo.desktop:\n            return desktop;\n        }\n      },\n    );\n  }\n}","Hai un widget riutilizzabile che mostra layout differenti per ogni dispositivo.",{"id":47,"position":48,"title":49,"body":50,"code_snippet":51,"code_language":30,"expected_result":52,"demo_url":10,"video_url":10},59,4,"Costruire una griglia adattiva con GridView","Un caso comune è mostrare delle card in una griglia il cui numero di colonne cambia in base alla larghezza. Usiamo `GridView.builder` con `SliverGridDelegateWithMaxCrossAxisExtent`, che calcola automaticamente le colonne fissando una larghezza massima per ogni elemento.","class GrigliaCard extends StatelessWidget {\n  const GrigliaCard({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return GridView.builder(\n      padding: const EdgeInsets.all(16),\n      gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(\n        maxCrossAxisExtent: 250, \u002F\u002F larghezza massima di ogni card\n        mainAxisSpacing: 12,\n        crossAxisSpacing: 12,\n        childAspectRatio: 3 \u002F 2,\n      ),\n      itemCount: 12,\n      itemBuilder: (context, index) {\n        return Card(\n          elevation: 2,\n          child: Center(child: Text('Elemento ${index + 1}')),\n        );\n      },\n    );\n  }\n}","La griglia mostra automaticamente più colonne su schermi larghi e meno su quelli stretti.",{"id":54,"position":55,"title":56,"body":57,"code_snippet":58,"code_language":30,"expected_result":59,"demo_url":10,"video_url":10},60,5,"Gestire righe flessibili con Expanded e Wrap","Per disposizioni orizzontali, `Expanded` e `Flexible` distribuiscono lo spazio tra i figli di una `Row`. Quando però il contenuto rischia di traboccare su schermi piccoli, `Wrap` manda automaticamente gli elementi a capo. Combiniamo i due approcci usando `LayoutResponsivo`.","class PannelloInfo extends StatelessWidget {\n  const PannelloInfo({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    final box1 = Container(height: 120, color: Colors.blue.shade100, child: const Center(child: Text('Box 1')));\n    final box2 = Container(height: 120, color: Colors.green.shade100, child: const Center(child: Text('Box 2')));\n    final box3 = Container(height: 120, color: Colors.orange.shade100, child: const Center(child: Text('Box 3')));\n\n    return LayoutResponsivo(\n      \u002F\u002F Su mobile impiliamo in colonna\n      mobile: Column(\n        children: [box1, const SizedBox(height: 12), box2, const SizedBox(height: 12), box3],\n      ),\n      \u002F\u002F Su tablet usiamo Wrap per andare a capo se serve\n      tablet: Wrap(\n        spacing: 12,\n        runSpacing: 12,\n        children: [\n          SizedBox(width: 300, child: box1),\n          SizedBox(width: 300, child: box2),\n          SizedBox(width: 300, child: box3),\n        ],\n      ),\n      \u002F\u002F Su desktop distribuiamo lo spazio con Expanded\n      desktop: Row(\n        children: [\n          Expanded(child: box1),\n          const SizedBox(width: 12),\n          Expanded(child: box2),\n          const SizedBox(width: 12),\n          Expanded(child: box3),\n        ],\n      ),\n    );\n  }\n}","I box si dispongono in colonna su mobile, a capo su tablet e affiancati su desktop.",{"id":61,"position":62,"title":63,"body":64,"code_snippet":65,"code_language":30,"expected_result":66,"demo_url":10,"video_url":10},61,6,"Assemblare la schermata finale","Mettiamo insieme tutti i pezzi in una `Scaffold`. Combiniamo il `PannelloInfo` responsive con la `GrigliaCard` adattiva, usando `MediaQuery` per gestire eventuale padding di sistema e un titolo che cambia in base al dispositivo.","class SchermataResponsive extends StatelessWidget {\n  const SchermataResponsive({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    final larghezza = MediaQuery.of(context).size.width;\n    final tipo = tipoDispositivo(larghezza);\n\n    return Scaffold(\n      appBar: AppBar(\n        title: Text('Layout ${tipo.name}'),\n      ),\n      body: SafeArea(\n        child: Column(\n          children: [\n            const Padding(\n              padding: EdgeInsets.all(16),\n              child: PannelloInfo(),\n            ),\n            const Divider(),\n            const Expanded(child: GrigliaCard()),\n          ],\n        ),\n      ),\n    );\n  }\n}","Eseguendo l'app e ridimensionando la finestra (o ruotando il dispositivo) il layout si adatta dinamicamente.",{"id":68,"position":69,"title":70,"body":71,"code_snippet":10,"code_language":30,"expected_result":72,"demo_url":10,"video_url":10},62,7,"Best practice e consigli finali","Alcuni accorgimenti per layout responsive solidi:\n\n- **Preferisci `LayoutBuilder` a `MediaQuery`** quando un widget non occupa tutto lo schermo (es. dentro un `Drawer` o un pannello).\n- **Evita valori fissi** di larghezza\u002Faltezza dove possibile: usa `Expanded`, `Flexible` e `FractionallySizedBox`.\n- **Testa con il DevTools** e con la modalità *Resize* su desktop\u002Fweb per verificare i breakpoint.\n- **Rispetta i SafeArea**: usa il widget `SafeArea` per evitare notch e barre di sistema.\n- **Considera `MediaQuery.textScalerOf(context)`** per supportare l'accessibilità e i testi ingranditi.\n\nCon questi strumenti la tua app sarà pronta per girare bene su qualsiasi schermo.","Conosci le linee guida per mantenere il layout robusto su tutti i dispositivi.",[],1781247855837]