Skip to Content

Input Utente

TextField

Descrizione

TextField è il widget di base per l’inserimento di testo da parte dell’utente.
Supporta input singola linea o multilinea, personalizzazioni grafiche, validazioni, icone, e molto altro.

Note

È usato per form, login, ricerca, commenti e qualunque input utente.


Attributi utili

AttributoTipoDescrizione
controllerTextEditingController?Controlla e accede al contenuto del campo di testo
decorationInputDecoration?Personalizza il campo (label, hint, icone, bordi, ecc.)
keyboardTypeTextInputType?Specifica il tipo di tastiera (email, numero, testo, ecc.)
obscureTextboolNasconde il testo (utile per password)
onChangedFunction(String)?Callback chiamata ogni volta che il testo cambia
onSubmittedFunction(String)?Chiamata quando l’utente preme invio
maxLinesint?Numero massimo di righe (default: 1)
readOnlyboolRende il campo non modificabile
enabledbool?Abilita/disabilita il campo

Esempio

TextField( decoration: InputDecoration( labelText: 'Email', border: OutlineInputBorder(), prefixIcon: Icon(Icons.email), ), keyboardType: TextInputType.emailAddress, onChanged: (value) { print('Email inserita: $value'); }, )

Esercizio

  • Crea un form con 2 TextField: uno per l’email e uno per la password (con obscureText a true). Aggiungi un pulsante “Login” che stampa i valori inseriti.

Esercizio Bonus

Crea un widget CustomTextField che:

  • accetta label, icon e isPassword come parametri,
  • imposta automaticamente il tipo di tastiera e il bordo,
  • fornisce un modo per accedere al valore corrente (tramite controller).

Uso di TextEditingController e ciclo di vita

Quando hai bisogno di accedere direttamente al contenuto di un TextField, ad esempio per leggere o impostare il testo, puoi usare un TextEditingController. Questo oggetto gestisce il valore del campo e consente anche di ascoltare le modifiche.

💡
Tip

È importante creare il controller in un StatefulWidget e ricordarsi di chiamare dispose() per evitare memory leak.


Esempio completo

class EmailInput extends StatefulWidget { @override State<EmailInput> createState() => _EmailInputState(); } class _EmailInputState extends State<EmailInput> { final TextEditingController _controller = TextEditingController(); @override void dispose() { _controller.dispose(); // Importante: libera risorse super.dispose(); } void _submit() { final email = _controller.text; print('Email inserita: $email'); } @override Widget build(BuildContext context) { return Column( children: [ TextField( controller: _controller, decoration: InputDecoration(labelText: 'Email'), ), ElevatedButton( onPressed: _submit, child: Text('Invia'), ), ], ); } }
Note

TextEditingController è utile anche per:

  • precompilare campi (controller.text = "valore iniziale";)
  • aggiornare dinamicamente il contenuto da codice
  • ascoltare modifiche con addListener

TextEditingController con TextFormField e validator

Se stai lavorando con un Form, puoi combinare TextEditingController e validator per:

  • gestire il contenuto del campo di input,
  • validare il testo inserito,
  • accedere facilmente al valore al momento dell’invio.

Esempio completo con validazione

class LoginForm extends StatefulWidget { @override State<LoginForm> createState() => _LoginFormState(); } class _LoginFormState extends State<LoginForm> { final _formKey = GlobalKey<FormState>(); final TextEditingController _emailController = TextEditingController(); @override void dispose() { _emailController.dispose(); super.dispose(); } void _submitForm() { if (_formKey.currentState!.validate()) { final email = _emailController.text; print('Login con email: $email'); } } @override Widget build(BuildContext context) { return Form( key: _formKey, child: Column( children: [ TextFormField( controller: _emailController, decoration: InputDecoration(labelText: 'Email'), keyboardType: TextInputType.emailAddress, validator: (value) { if (value == null || value.isEmpty) { return 'Inserisci un\'email'; } if (!value.contains('@')) { return 'Email non valida'; } return null; }, ), SizedBox(height: 16), ElevatedButton( onPressed: _submitForm, child: Text('Login'), ), ], ), ); } }

💡
Tip

Puoi usare più TextEditingController per gestire più campi del form, ad esempio per email e password. Ricorda sempre di eliminare tutti i controller in dispose().


Checkbox

Descrizione

Checkbox è un widget per selezioni binarie (vero/falso).
Viene spesso utilizzato in form, impostazioni e preferenze utente.

Note

Può essere combinato con ListTile per un layout più accessibile e ordinato.


Attributi utili

AttributoTipoDescrizione
valueboolStato attuale del checkbox (true/false)
onChangedFunction(bool?)Callback quando l’utente cambia lo stato
activeColorColor?Colore della spunta quando selezionata
checkColorColor?Colore della spunta (segno di check)
fillColorMaterialStateProperty<Color?>?Colore del riempimento
tristateboolPermette uno stato nullo (null, true, false)

Esempio

bool isChecked = false; Checkbox( value: isChecked, onChanged: (bool? newValue) { setState(() { isChecked = newValue ?? false; }); }, )

Esercizio

Crea una lista di 3 checkbox con etichette diverse. Ogni checkbox deve aggiornare il suo stato individualmente.


Esercizio Bonus

Crea un widget CustomCheckboxTile che:

  • accetta un titolo e un booleano come input,
  • visualizza il titolo accanto alla checkbox,
  • usa un ListTile per l’allineamento,
  • cambia il colore in base allo stato selezionato.

CheckboxListTile

Descrizione

CheckboxListTile combina una Checkbox con un layout in stile lista.
Fornisce titolo, sottotitolo e supporto per icone, rendendolo perfetto per le impostazioni.

Note

Usa ListTile internamente. Ottimo per UX coerente.


Attributi utili

AttributoTipoDescrizione
valueboolStato della checkbox
onChangedFunction(bool?)Callback al cambiamento
titleWidgetTitolo principale
subtitleWidget?Testo secondario sotto il titolo
secondaryWidget?Widget alla fine (es. icona)
controlAffinityListTileControlAffinityPosizione della checkbox (leading/trailing)

Esempio

CheckboxListTile( title: Text('Accetta termini'), value: isChecked, onChanged: (bool? value) { setState(() { isChecked = value ?? false; }); }, )

Esercizio

  • Crea un elenco di 3 CheckboxListTile per attivare/disattivare diverse preferenze utente.

Switch

Descrizione

Switch è un widget per controlli binari ON/OFF.
Simile a un interruttore di impostazioni.


Attributi utili

AttributoTipoDescrizione
valueboolStato dell’interruttore
onChangedFunction(bool)Callback al cambiamento
activeColorColor?Colore quando attivo
inactiveThumbColorColor?Colore del pollice da spento
inactiveTrackColorColor?Colore dello sfondo da spento

Esempio

Switch( value: isSwitched, onChanged: (bool value) { setState(() { isSwitched = value; }); }, )

Esercizio utile

Crea una schermata con uno Switch che cambia tema (chiaro/scuro).


SwitchListTile

Descrizione

SwitchListTile è la versione “tile” del widget Switch.
Fornisce un layout con testo e interruttore integrato.


Attributi utili

AttributoTipoDescrizione
valueboolStato dell’interruttore
onChangedFunction(bool)Callback al cambiamento
titleWidgetTitolo principale
subtitleWidget?Testo secondario sotto il titolo
secondaryWidget?Icona o altro widget finale

Esempio

SwitchListTile( title: Text('Notifiche'), value: isEnabled, onChanged: (bool value) { setState(() { isEnabled = value; }); }, )

Esercizio

  • Crea un elenco di 2 SwitchListTile per abilitare/disabilitare impostazioni utente.

Slider

Descrizione

Slider è un widget che consente all’utente di selezionare un valore da un intervallo continuo.


Attributi utili

AttributoTipoDescrizione
valuedoubleValore corrente del cursore
onChangedFunction(double)Callback durante il movimento
mindoubleValore minimo selezionabile
maxdoubleValore massimo selezionabile
divisionsint?Suddivisione in step discreti (opzionale)
labelString?Etichetta mostrata sopra il cursore

Esempio pratico

Slider( value: sliderValue, min: 0, max: 100, divisions: 10, label: '${sliderValue.round()}', onChanged: (double value) { setState(() { sliderValue = value; }); }, )

Esercizio

  • Crea uno Slider che controlla la dimensione di un testo visualizzato in tempo reale.

.adaptive

Descrizione

Molti widget come Switch, Checkbox e CupertinoSwitch hanno una versione .adaptive. Questa variante sceglie automaticamente lo stile appropriato in base alla piattaforma (Android o iOS).

Note

È utile per avere UI coerenti senza scrivere codice condizionale con Platform.isIOS o simili.


Esempio pratico

Switch.adaptive( value: isDarkMode, onChanged: (bool value) { setState(() { isDarkMode = value; }); }, )

Esercizio

  • Crea una schermata con uno Switch.adaptive che attiva/disattiva una modalità scura e mostra uno Checkbox.adaptive per confermare un’opzione.

Esercizio Bonus

Crea un widget PlatformSwitch che:

  • Usa Switch.adaptive
  • Mostra un’icona diversa su iOS e Android (es. Icons.apple vs Icons.android)
  • Cambia dinamicamente il colore della UI al cambio stato

GestureDetector

Descrizione

GestureDetector intercetta e gestisce gesture dell’utente: tap, doppio tap, swipe, long press, ecc.

Note

Usalo per rendere tappabile qualunque widget.


Attributi utili

AttributoTipoDescrizione
onTapFunction()?Chiamato al tocco singolo
onDoubleTapFunction()?Chiamato al doppio tocco
onLongPressFunction()?Chiamato dopo una pressione prolungata
onPanUpdateFunction(DragUpdateDetails)?Movimento durante trascinamento

Esempio

GestureDetector( onTap: () => print('Toccato!'), child: Container( padding: EdgeInsets.all(20), color: Colors.amber, child: Text('Tocca qui'), ), )

Esercizio

  • Crea un quadrato colorato che cambia colore ogni volta che viene toccato usando GestureDetector.

InkWell

Descrizione

InkWell è un widget che aggiunge un effetto visivo “ripple” quando viene toccato.

Note

Deve essere usato all’interno di un widget Material (es. Card, Container con Material).


Attributi utili

AttributoTipoDescrizione
onTapFunction()?Chiamato al tocco
onLongPressFunction()?Pressione prolungata
borderRadiusBorderRadius?Bordo arrotondato per l’effetto ripple

Esempio

InkWell( onTap: () => print('Ripple!'), borderRadius: BorderRadius.circular(12), child: Container( padding: EdgeInsets.all(20), color: Colors.teal, child: Text('Premi me'), ), )

Esercizio utile

  • Crea una card cliccabile con InkWell che mostra un messaggio quando premuta.

Buttons in Flutter

Descrizione

I pulsanti (button) sono widget fondamentali. Flutter fornisce un set ampio di button personalizzabili, ciascuno pensato per contesti diversi (Material, Cupertino, azioni floating, pulsanti testuali, ecc.).


ElevatedButton

Descrizione

Pulsante rialzato con effetto ombra, usato per azioni primarie.

Attributi utili

AttributoTipoDescrizione
onPressedFunction()Azione al click
childWidgetContenuto del bottone
styleButtonStyle?Stile (colore, padding, forma, ecc.)

Esempio

ElevatedButton( onPressed: () => print('Premuto!'), child: Text('Invia'), ) //Esempio con style ElevatedButton( onPressed: () {}, style: ElevatedButton.styleFrom( backgroundColor: Colors.teal, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16), elevation: 4, ), child: Text('Conferma'), )

TextButton

Descrizione

Pulsante piatto senza sfondo o bordo, per azioni secondarie.

Esempio

TextButton( onPressed: () {}, child: Text('Annulla'), ) TextButton( onPressed: () {}, style: TextButton.styleFrom( foregroundColor: Colors.orange, padding: EdgeInsets.all(16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: Text('Annulla'), )

OutlinedButton

Descrizione

Simile a TextButton, ma con un bordo visibile.

Esempio

OutlinedButton( onPressed: () {}, child: Text('Info'), ) OutlinedButton( onPressed: () {}, style: OutlinedButton.styleFrom( side: BorderSide(color: Colors.red), foregroundColor: Colors.red, padding: EdgeInsets.symmetric(horizontal: 16), ), child: Text('Info'), )

IconButton

Descrizione

Pulsante che contiene solo un’icona, utile per toolbar o azioni rapide.

Esempio

IconButton( onPressed: () {}, icon: Icon(Icons.thumb_up), )

FloatingActionButton

Descrizione

Pulsante fluttuante usato spesso per azione primaria su una schermata.

Esempio

FloatingActionButton( onPressed: () {}, child: Icon(Icons.add), )

CupertinoButton

Descrizione

Pulsante in stile iOS (Cupertino), usato in app native Apple.

Esempio

CupertinoButton( onPressed: () {}, child: Text('iOS Style'), )

Descrizione

Non è un bottone classico, ma consente di selezionare un valore da una lista.

Attributi utili

AttributoTipoDescrizione
valueTValore attualmente selezionato
itemsList<DropdownMenuItem<T>>Elementi selezionabili
onChangedFunction(T?)Callback alla selezione
hintWidget?Testo mostrato prima della selezione
isExpandedboolAllarga il bottone a tutta la larghezza

Esempio Base

DropdownButton<String>( value: selectedValue, items: ['Uno', 'Due', 'Tre'] .map((e) => DropdownMenuItem(value: e, child: Text(e))) .toList(), onChanged: (value) { setState(() { selectedValue = value!; }); }, )

Esempio avanzato con icone

DropdownButton<String>( value: selected, items: [ DropdownMenuItem( value: 'home', child: Row( children: [Icon(Icons.home), SizedBox(width: 8), Text('Home')], ), ), DropdownMenuItem( value: 'settings', child: Row( children: [Icon(Icons.settings), SizedBox(width: 8), Text('Settings')], ), ), ], onChanged: (value) => setState(() => selected = value!), )

Paragonabile alla select ma con alcune differenze rispetto a HTML

  • In Flutter puoi personalizzare ogni voce (es. icone, padding).
  • Il menu viene disegnato con Overlay, quindi non è parte del layout fisso.
  • Supporta anche DropdownButtonFormField per validazione nei form.

Decorazione avanzata di Widget con WidgetStateProperty

La classe ButtonStyle accetta WidgetStateProperty<T> per molte delle sue proprietà (tra cui padding, backgroundColor, foregroundColor, side, ecc.). Questo ci consente di definire lo style in base allo stato in cui si trova il widget come pressed, hovered

WidgetStatePropertyAll

WidgetStatePropertyAll o WidgetStateProperty.all() equivale a definire una proprietà per tutti gli stati lo stesso avviene quando usiamo ClasseButton.styleFrom() come visto in precedenza


Esercizio utile

  • Crea una schermata con tutti i principali pulsanti Flutter, ciascuno con un’azione diversa.

Esercizio bonus

Crea un widget CustomButton che:

  • Usa ElevatedButton
  • Accetta testo, colore e icona opzionale
  • Può disabilitarsi con una proprietà booleana

Divider

Descrizione

Divider è un widget semplice usato per separare visivamente contenuti verticali, come elementi in una lista, sezioni in una colonna, o gruppi di informazioni.

Viene rappresentato come una linea orizzontale, con colore, spessore e margini personalizzabili.


Attributi utili

AttributoDescrizione
colorColore della linea (di default usa il colore del tema)
thicknessSpessore della linea (default: 0.0, visibile solo se height > 0)
heightAltezza totale dell’area occupata dal divider (include anche margini verticali)
indentSpazio vuoto a sinistra (in pixel)
endIndentSpazio vuoto a destra (in pixel)

Esempio

Divider() Divider( color: Colors.grey, thickness: 2, height: 32, indent: 16, endIndent: 16, )

Divider verticale: VerticalDivider

Se vuoi separare elementi orizzontali (es. all’interno di una Row), puoi usare VerticalDivider:

Row( children: [ Expanded(child: Text('A')), VerticalDivider(color: Colors.black, thickness: 1), Expanded(child: Text('B')), ], )
Note

VerticalDivider funziona solo all’interno di un contenitore che ha altezza, come una Row con SizedBox o Container.