TextField et TextEditingController - Bases de la saisie de texte
Introduction au TextField
Section titled “Introduction au TextField”Le TextField est le widget fondamental pour la saisie de texte dans Flutter. Pour contrôler son contenu, on utilise un TextEditingController.
TextField de base
Section titled “TextField de base”Voici un exemple complet d’utilisation du TextField avec un contrôleur :
import 'package:flutter/material.dart';
class MainScreen extends StatefulWidget { const MainScreen({Key? key}) : super(key: key);
@override State<MainScreen> createState() => _MainScreenState();}
class _MainScreenState extends State<MainScreen> { late final TextEditingController nameController; String currentText = '';
@override void initState() { super.initState(); nameController = TextEditingController(); nameController.addListener(() { print('text : ${nameController.text}'); print('selection : ${nameController.selection}'); setState(() => currentText = nameController.text); }); }
@override Widget build(BuildContext context) { return Scaffold( body: Center( child: ConstrainedBox( constraints: BoxConstraints(maxWidth: 320), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ TextField( controller: nameController, decoration: InputDecoration( label: Text('Nom'), ), ), Text('Nom : $currentText') ], ), ), ), ); }
@override void dispose() { nameController.dispose(); super.dispose(); }}Configuration du TextField
Section titled “Configuration du TextField”InputDecoration
Section titled “InputDecoration”L’InputDecoration permet de personnaliser l’apparence du champ :
TextField( controller: controller, decoration: InputDecoration( label: Text('Email'), hintText: 'Entrez votre email', prefixIcon: Icon(Icons.email), suffixIcon: Icon(Icons.clear), filled: true, fillColor: Colors.grey[100], border: OutlineInputBorder(), errorText: hasError ? 'Email invalide' : null, ),)Types de clavier
Section titled “Types de clavier”La propriété keyboardType permet de configurer le clavier adapté :
TextField( keyboardType: TextInputType.emailAddress, // Clavier email)
TextField( keyboardType: TextInputType.phone, // Clavier numérique)
TextField( keyboardType: TextInputType.multiline, // Texte multiligne maxLines: null,)Types disponibles :
TextInputType.text- Clavier par défautTextInputType.emailAddress- Clavier emailTextInputType.phone- Clavier téléphoneTextInputType.number- Clavier numériqueTextInputType.multiline- Texte multiligneTextInputType.datetime- Saisie de date/heure
Écouteurs d’événements
Section titled “Écouteurs d’événements”TextField( onChanged: (value) => print('Texte modifié: $value'), onEditingComplete: () => print('Édition terminée'), onSubmitted: (value) => print('Formulaire soumis: $value'), onTap: () => print('Champ tapé'),)Formatage du texte
Section titled “Formatage du texte”Il est possible de formater automatiquement le texte saisi avec des TextInputFormatter :
class SpaceFormatter extends TextInputFormatter { @override TextEditingValue formatEditUpdate( TextEditingValue oldValue, TextEditingValue newValue) { if (newValue.text.isEmpty || newValue.text.length == 1) return newValue;
final formattedText = newValue.text.replaceAll(' ', '').split('').join(' '); return TextEditingValue( text: formattedText, selection: TextSelection.collapsed(offset: formattedText.length), ); }}
// UtilisationTextField( inputFormatters: [SpaceFormatter()],)Bonnes pratiques
Section titled “Bonnes pratiques”Gestion de la mémoire
Section titled “Gestion de la mémoire”Toujours disposer des contrôleurs pour éviter les fuites mémoire :
class FormScreen extends StatefulWidget { @override _FormScreenState createState() => _FormScreenState();}
class _FormScreenState extends State<FormScreen> { final _emailController = TextEditingController(); final _passwordController = TextEditingController();
@override void dispose() { _emailController.dispose(); _passwordController.dispose(); super.dispose(); }
@override Widget build(BuildContext context) { // Formulaire... }}Accessibilité
Section titled “Accessibilité”Améliorer l’accessibilité avec des labels appropriés :
TextFormField( decoration: InputDecoration( labelText: 'Email', helperText: 'Votre adresse email professionnelle', ), keyboardType: TextInputType.emailAddress, textInputAction: TextInputAction.next, validator: validateEmail,)Sauvegarde automatique
Section titled “Sauvegarde automatique”Implémenter une sauvegarde automatique des données :
class AutoSaveForm extends StatefulWidget { @override _AutoSaveFormState createState() => _AutoSaveFormState();}
class _AutoSaveFormState extends State<AutoSaveForm> { final _emailController = TextEditingController(); Timer? _debounceTimer;
@override void initState() { super.initState(); _emailController.addListener(_onTextChanged); _loadSavedData(); }
void _onTextChanged() { _debounceTimer?.cancel(); _debounceTimer = Timer(Duration(milliseconds: 500), () { _saveData(); }); }
void _saveData() { // Sauvegarder localement SharedPreferences.getInstance().then((prefs) { prefs.setString('draft_email', _emailController.text); }); }
void _loadSavedData() { SharedPreferences.getInstance().then((prefs) { final savedEmail = prefs.getString('draft_email'); if (savedEmail != null) { _emailController.text = savedEmail; } }); }
@override Widget build(BuildContext context) { return TextField( controller: _emailController, decoration: InputDecoration( labelText: 'Email', suffixIcon: Icon(Icons.cloud_done, color: Colors.green), ), ); }
@override void dispose() { _debounceTimer?.cancel(); _emailController.dispose(); super.dispose(); }}