Flutter Widgets — i mattoni fondamentali dell'interfaccia utente nel framework Google Flutter, rilasciato nella versione stabile 1.0 a dicembre 2018. In Flutter, tutto è un widget: da schermi e pulsanti a spaziature e allineamenti. I widget formano un albero (widget tree) che Flutter renderizza sul proprio motore Skia/Impeller, bypassando i componenti nativi della piattaforma. Secondo Google I/O (2025), Flutter è utilizzato in oltre 500.000 app su Google Play e App Store. L'architettura Flutter divide i widget in StatelessWidget (immutabili) e StatefulWidget (con stato mutabile tramite un oggetto State).
Punti Chiave
Flutter Widgets — tutti gli elementi UI nel framework Flutter, implementati come classi Dart immutabili. Un widget è la configurazione di un elemento UI: la sua dimensione, colore, posizione e gestori di eventi. A differenza di Android (XML + View) o iOS (Storyboard + UIView), Flutter non usa componenti nativi — tutto viene disegnato dal motore Skia (Android/iOS/Linux) o Impeller (iOS/macOS) su una Canvas. Questo garantisce un aspetto coerente su tutte le piattaforme senza discrepanze di piattaforma. Flutter viene fornito con due insiemi di widget: Material Widgets (Google Material Design 3 per Android/web) e Cupertino Widgets (Apple HIG per iOS/macOS). Lo sviluppatore può combinare entrambi gli insiemi in una singola applicazione. Ogni widget ha un metodo build() che restituisce un widget figlio o una loro composizione — così viene costruito l'albero di widget.
Flutter opera con tre alberi: Widget Tree (configurazione, creata dallo sviluppatore), Element Tree (mappatura del widget alla sua posizione nell'albero, gestita dal framework) e Render Tree (oggetti che calcolano il layout ed eseguono la pittura). Un Widget crea un Element, che crea un RenderObject. L'Element viene riutilizzato quando la configurazione cambia (rebuild) — questo è il meccanismo di ottimizzazione di Flutter: se il tipo di widget e la key corrispondono, l'Element non viene ricreato ma aggiornato con la nuova configurazione. Comprendere i tre alberi è la chiave per ottimizzare le prestazioni delle applicazioni Flutter.
StatelessWidget — un widget che non memorizza stato interno. Riceve parametri tramite il costruttore e li mostra senza possibilità di modifica dopo il build. StatelessWidget è ideale per elementi statici: intestazioni, icone, avatar, elenchi con dati fissi. Il metodo build() viene chiamato una volta alla creazione e quando il widget padre cambia. Poiché StatelessWidget non ha stato, non richiede un oggetto State separato — build() è definito direttamente nella classe del widget.
import 'package:flutter/material.dart';
class ProfileHeader extends StatelessWidget {
final String name;
final String avatarUrl;
const ProfileHeader({super.key, required this.name, required this.avatarUrl});
@override
Widget build(BuildContext context) {
return Row(
children: [
CircleAvatar(
radius: 24,
backgroundImage: NetworkImage(avatarUrl),
),
const SizedBox(width: 12),
Text(
name,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
);
}
}ProfileHeader — un StatelessWidget che riceve name e avatarUrl tramite il costruttore. CircleAvatar mostra l'avatar, Text mostra il nome. Il widget non può modificare questi valori dopo la creazione. Usare un costruttore const (const ProfileHeader) permette a Flutter di riutilizzare l'istanza del widget durante il rebuild del padre — una micro-ottimizzazione raccomandata per tutti i StatelessWidget.
StatefulWidget — un widget con stato mutabile memorizzato in un oggetto State separato. Lo StatefulWidget stesso è immutabile, come StatelessWidget. La parte mutabile è delegata a State: State è un oggetto creato una volta che sopravvive a molteplici rebuild del widget. Quando lo stato cambia (setState()), Flutter chiama build() su State, aggiornando l'UI. StatefulWidget è usato per elementi interattivi: contatori, campi di testo, checkbox, animazioni, timer.
import 'package:flutter/material.dart';
class LikeButton extends StatefulWidget {
const LikeButton({super.key});
@override
State<LikeButton> createState() => _LikeButtonState();
}
class _LikeButtonState extends State<LikeButton> {
bool liked = false;
int count = 42;
void _toggleLike() {
setState(() {
liked = !liked;
count += liked ? 1 : -1;
});
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _toggleLike,
child: Text(liked ? '♥ $count' : '♡ $count'),
);
}
}LikeButton — un StatefulWidget con la classe State _LikeButtonState. I campi liked e count sono lo stato memorizzato in State e non vengono resettati al rebuild. setState() notifica a Flutter che l'UI deve essere ricostruita. Flutter non ricrea State ad ogni rebuild del padre — solo quando la configurazione cambia (key o tipo di widget). In IT Sectr, usiamo StatelessWidget per la visualizzazione e StatefulWidget per i componenti interattivi, seguendo il principio di minimizzare StatefulWidget fino ai confini della mutazione.
Widget Tree — una struttura gerarchica di widget che descrive l'UI dell'applicazione. Flutter converte il Widget Tree in Element Tree: ogni Widget crea un Element, che traccia la sua posizione nell'albero e la sua connessione a un RenderObject. Il Render Tree esegue il layout (determinazione di dimensioni e posizioni) e la pittura (rendering). L'Element è un livello di ottimizzazione chiave: se il tipo di widget e la key non sono cambiati durante un rebuild, l'Element viene riutilizzato, aggiornando la configurazione senza ricreare il RenderObject. Questo garantisce le prestazioni di Flutter a frame rate elevati (60/120 FPS).
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Widget Flutter')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.flutter_dash, size: 80),
const SizedBox(height: 16),
const Text(
'Ciao, Flutter!',
style: TextStyle(fontSize: 24),
),
],
),
),
);
}
}Albero di widget HomeScreen: Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold è il widget radice di layout di Material Design. Center centra la sua Column figlia. Column dispone i figli verticalmente con allineamento centrato (mainAxisAlignment.center). Flutter calcola il layout dall'alto verso il basso (i vincoli sono passati dal padre) e le dimensioni dal basso verso l'alto (sizedByParent o dimensionamento dai figli).
BuildContext — un descrittore della posizione del widget nell'Element Tree. Ogni metodo build() riceve un BuildContext, attraverso il quale il widget può accedere a: MediaQuery (dimensioni dello schermo, orientamento, densità di pixel, area sicura), Theme (MaterialThemeData o CupertinoThemeData), Navigator (pila di navigazione), ScaffoldMessenger (SnackBar), InheritedWidget (passaggio di dati verso il basso nell'albero). BuildContext non deve essere salvato dopo il completamento di build() o usato al di fuori di un contesto sincrono — questo causa errori come “Scaffold.of() called with a context that does not contain a Scaffold”. Invece di salvare il context, usa il widget Builder o il pattern InheritedWidget per accedere ai dati.
Key — un parametro opzionale del costruttore di ogni widget (super.key). Key aiuta Flutter a identificare un widget quando l'ordine o il numero di elementi in una lista cambia. Senza key, Flutter confronta i widget per tipo e posizione; quando si aggiunge un elemento in mezzo a una lista senza key, Flutter riutilizza l'Element per il widget sbagliato, causando bug di stato (StatefulWidget) e problemi di animazione. Usa ValueKey (identificatore univoco) per le liste, ObjectKey (basato sull'oggetto dati), UniqueKey (garantito univoco ad ogni rebuild — per ricreazione forzata).
Flutter SDK (versione stabile 3.3+, Dart 3+) include oltre 200 widget integrati divisi in categorie: Layout (Row, Column, Stack, Container, Expanded, Flexible, Wrap, GridView, ListView, CustomScrollView), Material Design (Scaffold, AppBar, Card, Drawer, BottomNavigationBar, FloatingActionButton, TabBar, Chip, DataTable), Cupertino (CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton, CupertinoTabBar), Painting & Effects (Opacity, DecoratedBox, ClipRect, Transform, BackdropFilter, ShaderMask), Async (FutureBuilder, StreamBuilder) e Accessibility (Semantics, MergeSemantics, ExcludeSemantics). I widget di layout sono la base di qualsiasi UI Flutter: Row per sequenze orizzontali, Column per verticali, Stack per elementi sovrapposti, Container con BoxDecoration per decorazione.
| Categoria | Widget chiave | Scopo |
|---|---|---|
| Layout | Row, Column, Stack, Container, Expanded, Flexible | Posizionamento e dimensionamento dei figli |
| Material | Scaffold, AppBar, Card, Drawer, FAB, TabBar | Componenti UI Material Design 3 |
| Cupertino | CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton | Componenti in stile iOS |
| Painting | Opacity, ClipRect, Transform, DecoratedBox, BackdropFilter | Effetti visivi e clipping |
| Async | FutureBuilder, StreamBuilder | Caricamento dati asincrono con stati UI |
| Accessibility | Semantics, MergeSemantics | Markup semantico per screen reader |
Domande Frequenti
StatelessWidget non ha stato interno — tutti i dati sono passati tramite il costruttore e non cambiano. StatefulWidget memorizza lo stato mutabile in un oggetto State separato che sopravvive ai rebuild. Il cambiamento di stato chiama setState(), e Flutter ricostruisce l'UI. Usa StatelessWidget per elementi immutabili; usa StatefulWidget per elementi interattivi.
BuildContext è un descrittore della posizione del widget nell'Element Tree, passato al metodo build(). Attraverso il context, un widget accede a MediaQuery, Theme, Navigator, ScaffoldMessenger e InheritedWidget. BuildContext non deve essere salvato dopo il completamento di build(). Per accedere ai dati, usa il widget Builder o InheritedWidget.
Sì, Flutter usa Dart come unico linguaggio di programmazione. Dart è un linguaggio tipizzato staticamente con null safety, sound null safety, extension methods e pattern matching. Per iniziare, sono sufficienti le basi di Dart: classi, funzioni, async/await, collezioni. Dart viene compilato in codice nativo (AOT) tramite Dart Native e in JavaScript (per il web) tramite Dart2JS.
No, Flutter supporta sei piattaforme: iOS, Android, Web, macOS, Windows, Linux. Oltre il 90% del codice è condiviso tra tutte le piattaforme. Gli adattamenti di piattaforma (fotocamera, filesystem) sono implementati tramite plugin o platform channels. Per il desktop, Flutter utilizza la shell finestra Flutter Desktop; per il web, utilizza il motore CanvasKit (WebGL) o il renderer HTML.
Flutter raggiunge 60/120 FPS grazie a: motore 2D proprietario (Skia/Impeller), assenza di bridge nativo (a differenza di React Native), tre alberi (Widget → Element → Render) con riutilizzo di Element quando tipo/key rimangono invariati, un algoritmo di layout a passaggio unidirezionale (vincoli verso il basso, dimensioni verso l'alto) e RepaintBoundary per isolare il ripainting di singole aree dello schermo.
Riepilogo
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.
Leggi anche