Gestion des Entrées Utilisateur avec TextField dans Flutter

Le widget TextField de Flutter est l'élément fondamental pour permettre aux utilisateurs de saisir du texte, des nombres ou d'autres données dans une application. Sa flexibilité provient d'un large éventail de propriétés qui permettent de personnaliser son comportement et son apparence pour s'adapter à divers cas d'utilisation.

Le Contrôleur de Texte : TextEditingController

Le TextEditingController est essentiel pour interagir programmatiquement avec un TextField. Il permet de lire, définir ou effacer le texte du champ, et d'écouter les modifications en temps réel.

import 'package:flutter/material.dart';

class ChampDeSaisieControle extends StatefulWidget {
 @override
 _ChampDeSaisieControleState createState() => _ChampDeSaisieControleState();
}

class _ChampDeSaisieControleState extends State<ChampDeSaisieControle> {
 final TextEditingController _controleurSaisie = TextEditingController();
 String _dernierTexte = '';

 @override
 void initState() {
   super.initState();
   _controleurSaisie.addListener(_mettreAJourAffichage);
 }

 void _mettreAJourAffichage() {
   setState(() {
     _dernierTexte = _controleurSaisie.text;
   });
 }

 @override
 void dispose() {
   _controleurSaisie.dispose(); // Libérer les ressources
   super.dispose();
 }

 @override
 Widget build(BuildContext context) {
   return Column(
     children: [
       TextField(
         controller: _controleurSaisie,
         decoration: InputDecoration(
           hintText: 'Tapez votre message...',
           border: OutlineInputBorder(),
         ),
       ),
       Padding(
         padding: const EdgeInsets.symmetric(vertical: 10.0),
         child: Text('Texte actuel: "$_dernierTexte"'),
       ),
       ElevatedButton(
         onPressed: () {
           _controleurSaisie.clear(); // Efface le contenu du champ
         },
         child: Text('Vider le champ'),
       ),
     ],
   );
 }
}

Gestion du Focus avec FocusNode

Le FocusNode permet de suivre l'état du focus d'un TextField (s'il est sélectionné ou non) et de le manipuler (lui donner ou lui retirer le focus).

import 'package:flutter/material.dart';

class GestionnaireFocus extends StatefulWidget {
 @override
 _GestionnaireFocusState createState() => _GestionnaireFocusState();
}

class _GestionnaireFocusState extends State<GestionnaireFocus> {
 final FocusNode _nœudFocusChamp = FocusNode();
 String _statutFocus = 'Non focalisé';

 @override
 void initState() {
   super.initState();
   _nœudFocusChamp.addListener(_ecouterFocus);
 }

 void _ecouterFocus() {
   setState(() {
     _statutFocus = _nœudFocusChamp.hasFocus ? 'Champ focalisé' : 'Champ non focalisé';
   });
   print('Focus du champ: $_statutFocus');
 }

 @override
 void dispose() {
   _nœudFocusChamp.dispose(); // Important pour éviter les fuites de mémoire
   super.dispose();
 }

 @override
 Widget build(BuildContext context) {
   return Column(
     children: [
       TextField(
         focusNode: _nœudFocusChamp,
         decoration: InputDecoration(
           labelText: 'Entrée avec gestion de focus',
           border: OutlineInputBorder(),
         ),
       ),
       Padding(
         padding: const EdgeInsets.symmetric(vertical: 10.0),
         child: Text('État du focus: $_statutFocus'),
       ),
       ElevatedButton(
         onPressed: () {
           if (_nœudFocusChamp.hasFocus) {
             _nœudFocusChamp.unfocus(); // Retire le focus
           } else {
             FocusScope.of(context).requestFocus(_nœudFocusChamp); // Donne le focus
           }
         },
         child: Text('Basculer le focus'),
       ),
     ],
   );
 }
}

Personnalisation Visuelle avec InputDecoration

La propriété decoration, qui prend une instance de InputDecoration, est la clé pour styliser un TextField. Elle permet d'ajouter des étiquettes, des indices, des icônes, des messages d'erreur et de définir les bordures.

  • icon : Icône externe au champ.
  • labelText : Texte d'étiquette qui flotte au-dessus du champ lorsqu'il est focalisé.
  • hintText : Texte d'aide affiché lorsque le champ est vide.
  • helperText : Texte informatif en dessous du champ.
  • prefixIcon/suffixIcon : Icônes placées à l'intérieur du champ, respectivement au début et à la fin.
  • border : Définit le style de la bordure du champ (par exemple, OutlineInputBorder pour une bordure complète).
  • errorText : Message d'erreur affiché sous le champ.
import 'package:flutter/material.dart';

class StyleDeChamp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return TextField(
     decoration: InputDecoration(
       icon: Icon(Icons.email, color: Colors.blueGrey), // Icône extérieure
       labelText: 'Votre Email',
       labelStyle: TextStyle(color: Colors.deepPurple),
       hintText: 'exemple@domaine.com',
       helperText: 'Nous ne partagerons jamais votre email.',
       prefixIcon: Icon(Icons.alternate_email), // Icône à l'intérieur avant
       suffixIcon: IconButton(
         icon: Icon(Icons.clear, color: Colors.redAccent),
         onPressed: () { /* Action d'effacement */ },
       ),
       border: OutlineInputBorder(
         borderRadius: BorderRadius.circular(12.0),
       ),
       focusedBorder: OutlineInputBorder(
         borderSide: BorderSide(color: Colors.green, width: 2.0),
         borderRadius: BorderRadius.circular(12.0),
       ),
       filled: true,
       fillColor: Colors.lightBlue.shade50,
     ),
   );
 }
}

Configuration du Clavier et des Actions

Les propriétés keyboardType et textInputAction adaptent le clavier virtuel et l'action du bouton d'envoi.

  • keyboardType : Spécifie le type de clavier à afficher (TextInputType.number, TextInputType.emailAddress, TextInputType.phone, etc.).
  • textInputAction : Définit l'action du bouton en bas à droite du clavier (par exemple, TextInputAction.done, TextInputAction.next, TextInputAction.search, TextInputAction.send).
import 'package:flutter/material.dart';

class ClavierPersonnalise extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return Column(
     children: [
       TextField(
         keyboardType: TextInputType.phone, // Clavier optimisé pour les numéros de téléphone
         decoration: InputDecoration(
           labelText: 'Numéro de contact',
           hintText: 'Ex: 06 12 34 56 78',
           border: UnderlineInputBorder(),
         ),
       ),
       SizedBox(height: 20),
       TextField(
         textInputAction: TextInputAction.send, // Bouton "Envoyer" sur le clavier
         onSubmitted: (valeur) {
           print('Message à envoyer: $valeur');
           // Logique d'envoi...
         },
         decoration: InputDecoration(
           labelText: 'Envoyer un message',
           hintText: 'Votre message ici...',
           border: OutlineInputBorder(),
         ),
       ),
     ],
   );
 }
}

Transformation du Texte : obscureText et textCapitalization

  • obscureText : Lorsque défini à true, masque le texte saisi, utile pour les mots de passe.
  • textCapitalization : Contrôle la capitalisation auotmatique du texte (TextCapitalization.words pour chaque mot, TextCapitalization.sentences pour chaque phrase, TextCapitalization.characters pour toutes les lettres en majuscules, TextCapitalization.none par défaut).
import 'package:flutter/material.dart';

class TransformationDeTexte extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return Column(
     children: [
       TextField(
         obscureText: true, // Cache le texte (ex: pour un mot de passe)
         decoration: InputDecoration(
           labelText: 'Mot de passe sécurisé',
           border: OutlineInputBorder(),
         ),
       ),
       SizedBox(height: 20),
       TextField(
         textCapitalization: TextCapitalization.words, // La première lettre de chaque mot sera en majuscule
         decoration: InputDecoration(
           labelText: 'Nom complet',
           hintText: 'Entrez votre nom et prénom',
           border: OutlineInputBorder(),
         ),
       ),
     ],
   );
 }
}

Écoute des Changements avec onChanged

La propriété onChanged est un callback qui est appelé chaque fois que le texte du champ de saisie est modifié. C'est idéal pour la validation en temps réel ou la mise à jour de l'interface utilisateur.

import 'package:flutter/material.dart';

class EcouteurDeModifications extends StatefulWidget {
 @override
 _EcouteurDeModificationsState createState() => _EcouteurDeModificationsState();
}

class _EcouteurDeModificationsState extends State<EcouteurDeModifications> {
 String _saisieCourante = '';

 @override
 Widget build(BuildContext context) {
   return Column(
     children: [
       TextField(
         onChanged: (valeur) {
           setState(() {
             _saisieCourante = valeur;
           });
           print('Saisie actuelle: $valeur');
         },
         decoration: InputDecoration(
           labelText: 'Tapez quelque chose...',
           border: OutlineInputBorder(),
         ),
       ),
       Padding(
         padding: const EdgeInsets.symmetric(vertical: 10.0),
         child: Text('Texte dynamique: "$_saisieCourante"'),
       ),
     ],
   );
 }
}

Personnalisation du Curseur

Il est possible d'ajuster l'apparence du curseur de saisie à l'aide des propriétés cursorColor, cursorWidth et cursorRadius.

import 'package:flutter/material.dart';

class CurseurEsthetique extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return TextField(
     cursorColor: Colors.pink,
     cursorWidth: 5.0,
     cursorRadius: Radius.circular(4.0), // Curseur arrondi
     decoration: InputDecoration(
       labelText: 'Champ avec un curseur personnalisé',
       border: OutlineInputBorder(),
     ),
   );
 }
}

Limitation de la Longueur et Gestion du Compteur

Pour restreindre le nombre de caractères qu'un utilisateur peut saisir, utilisez maxLength. Par défaut, cela affiche un compteur de caractères sous le champ. Si vous souhaitez limiter la longueur sans afficher le compteur, vous pouvez le masquer et utiliser un TextInputFormatter.

  • maxLength : Définit le nombre maximal de caractères. Active le compteur par défaut.
  • inputFormatters : Une liste de formateurs qui peuvent modifier ou valider la saisie. LengthLimitingTextInputFormatter est utilisé pour l'application stricte de la limite.
  • counterText: '' (dans InputDecoration) : Cache le compteur visuel même si maxLength est défini.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; // Nécessaire pour LengthLimitingTextInputFormatter

class LimitationDeChamp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return Column(
     children: [
       TextField(
         maxLength: 15, // Limite à 15 caractères, avec compteur visible
         decoration: InputDecoration(
           labelText: 'Code postal (15 max, compteur visible)',
           border: OutlineInputBorder(),
         ),
       ),
       SizedBox(height: 20),
       TextField(
         maxLength: 10, // Définit la limite
         inputFormatters: [
           LengthLimitingTextInputFormatter(10), // Assure que la limite est appliquée
         ],
         decoration: InputDecoration(
           labelText: 'Numéro ID (10 max, sans compteur)',
           counterText: '', // Cache le compteur
           border: OutlineInputBorder(),
         ),
       ),
     ],
   );
 }
}

Étiquettes: Flutter Dart TextField UI Widget

Publié le 26 juin à 23h36