TextWatcher : ce que c'est, interface TextWatcher et implémentation dans Android

Auteur : IT Sectr Publié le : 2026-07-08 Temps de lecture : 6 min

TextWatcher est une interface Android qui permet de suivre les modifications de texte dans EditText et d'autres TextView en temps réel. Le développeur reçoit des notifications à trois étapes : avant la modification, pendant la modification et après la modification du contenu textuel. Selon Android Developers, 2026, TextWatcher est utilisé dans la plupart des applications pour la validation de saisie, le comptage de caractères, la mise en œuvre de recherche avec autocomplétion et le formatage dynamique de texte. L'interface est indispensable dans les formulaires où une réaction immédiate à chaque frappe de touche est requise.

Points clés

  • TextWatcher est une interface intégrée du SDK Android pour écouter les changements de texte dans TextView et EditText.
  • L'interface contient trois méthodes : beforeTextChanged, onTextChanged et afterTextChanged, chacune responsable de son étape de modification.
  • La méthode afterTextChanged est la plus pratique pour valider le champ après que l'utilisateur a terminé la saisie.
  • L'appel récursif est une erreur courante : modifier le texte à l'intérieur de TextWatcher conduit à une boucle infinie.
  • TextWatcher est utilisé dans les champs de recherche, la validation de formulaires, le comptage de caractères et le formatage automatique de numéros de téléphone.

Qu'est-ce que TextWatcher et pourquoi en a-t-on besoin ?

TextWatcher est une interface du package android.text qui notifie l'application des modifications de texte dans les objets Editable. À chaque saisie, suppression ou remplacement de caractère, TextWatcher appelle séquentiellement trois méthodes, transmettant des informations sur la position des modifications. Cela permet au développeur de réagir instantanément aux actions de l'utilisateur — sans boutons ni déclencheurs supplémentaires.

Les principaux cas d'utilisation incluent la validation de champs en temps réel : vérifier l'e-mail lors de la saisie de chaque caractère, compter les caractères restants dans un champ avec limite de longueur, implémenter une recherche avec requête différée via debounce. TextWatcher est également utilisé pour formater la saisie — par exemple, l'insertion automatique d'espaces dans un numéro de téléphone ou l'ajout d'un masque pour une date.

Selon Android Developers, TextWatcher est présent dans 70% des applications qui travaillent avec des formulaires. Des bibliothèques comme Material Design Components et TextInputEditText utilisent TextWatcher en interne pour gérer les états d'erreur et afficher des compteurs. Comprendre le fonctionnement de cette interface est essentiel pour tout développeur Android.

Comment fonctionne l'interface TextWatcher

TextWatcher se connecte à tout objet TextView ou EditText via la méthode addTextChangedListener. Lorsque l'utilisateur saisit ou supprime un caractère, Android appelle d'abord beforeTextChanged, puis onTextChanged, et enfin afterTextChanged. Les paramètres de chaque méthode contiennent des données sur la plage modifiée : position de début, nombre de caractères supprimés et nombre de caractères ajoutés.

Il est important de comprendre qu'après avoir appelé afterTextChanged, l'objet Editable contient déjà la valeur actuelle. Par conséquent, il est pratique de vérifier le texte final du champ dans afterTextChanged. Avant ce moment, les données ne sont pas encore complètement mises à jour. Les développeurs confondent souvent le but des méthodes et utilisent onTextChanged pour la validation finale, alors que le choix correct est afterTextChanged.

Particularités d'appel des méthodes

À chaque insertion, remplacement ou suppression de caractère, la chaîne d'appels est garantie de s'exécuter complètement. Cependant, si le texte est modifié dans afterTextChanged (via clear, append, insert), TextWatcher se déclenchera récursivement. C'est la cause la plus fréquente de StackOverflowError dans les formulaires Android. Pour éviter la récursion, on utilise un verrou indicateur.

Trois méthodes de TextWatcher : beforeTextChanged, onTextChanged, afterTextChanged

Chacune des trois méthodes joue son rôle dans le cycle de vie de la modification de texte. La méthode beforeTextChanged(CharSequence s, int start, int count, int after) est appelée avant l'application des modifications. Elle transmet l'état actuel de la chaîne, la position de début de la modification, le nombre de caractères supprimés et le nombre de caractères ajoutés. Ici, vous pouvez enregistrer la valeur précédente ou vérifier les conditions avant la modification.

La méthode onTextChanged est appelée pendant la modification, lorsque les caractères ont déjà été supprimés mais que les nouveaux ne sont pas encore insérés. Paramètres : le texte après la suppression, la position de début, le nombre de caractères supprimés et le nombre de caractères ajoutés. Cette méthode est pratique pour l'animation ou la journalisation, mais pas pour travailler avec le texte final réel — il n'est pas encore assemblé.

La méthode afterTextChanged est la plus demandée. Elle reçoit un objet Editable et est appelée après que les modifications ont été entièrement appliquées. Dans cette méthode, vous pouvez lire la valeur finale du champ, effectuer une validation, mettre à jour l'UI et modifier le texte (avec prudence en raison de la récursion).

Exemple d'implémentation de TextWatcher pour le comptage de caractères

Un exemple pratique est un compteur de caractères pour un champ de saisie qui se met à jour à chaque modification de texte. Un tel élément se trouve souvent dans les formulaires de commentaires, les publications et les messages avec limite de longueur. L'implémentation via TextWatcher ne nécessite que quelques lignes et aucune bibliothèque tierce.

kotlin
val editText = findViewById<EditText>(R.id.edit_text)
val counterText = findViewById<TextView>(R.id.counter)

editText.addTextChangedListener(object : TextWatcher {
    override fun beforeTextChanged(
        s: CharSequence?, start: Int,
        count: Int, after: Int
    ) {}

    override fun onTextChanged(
        s: CharSequence?, start: Int,
        before: Int, count: Int
    ) {}

    override fun afterTextChanged(s: Editable?) {
        val len = s?.length ?: 0
        counterText.text = "$len / 200"
    }
})

Dans l'exemple, la méthode afterTextChanged reçoit le contenu actuel du champ via le paramètre s de type Editable. La longueur du texte est mise à jour dans un TextView séparé. Dans ce cas, seul counterText est modifié, pas l'EditText lui-même, donc aucune boucle ne se produit. Pour une limite de 200 caractères, vous pouvez bloquer la saisie supplémentaire après dépassement.

Les méthodes beforeTextChanged et onTextChanged restent vides, car l'état final est suffisant pour le comptage de la longueur. Si vous devez journaliser chaque modification, du code peut être ajouté dans onTextChanged. Cette flexibilité fait de TextWatcher un outil universel pour tout scénario de saisie de texte.

TextWatcher pour la validation de champs en temps réel

La validation en temps réel améliore considérablement l'UX : l'utilisateur voit une erreur immédiatement après avoir saisi une valeur incorrecte, plutôt qu'après avoir cliqué sur le bouton d'envoi. TextWatcher permet la vérification instantanée de l'e-mail, du mot de passe, du numéro de téléphone et d'autres champs. Le résultat est affiché via setError sur l'EditText ou via un TextView séparé avec un message d'erreur.

kotlin
fun validateEmail(emailEditText: EditText) {
    emailEditText.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            val email = s?.toString () ?: ""
            if (email.isNotBlank() &&
                !Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
                emailEditText.error = "Invalid email address"
            } else {
                emailEditText.error = null
            }
        }

        override fun beforeTextChanged(...) {}
        override fun onTextChanged(...) {}
    })
}

L'exemple utilise le Patterns.EMAIL_ADDRESS intégré du SDK Android pour vérifier l'e-mail. Si le texte n'est pas vide et ne correspond pas au modèle, une erreur est définie sur le champ via la propriété error. Lorsque la saisie est correcte, l'erreur est effacée. Il est important de ne pas exécuter la validation sur un champ vide — l'utilisateur peut ne pas avoir encore commencé à saisir, et un message d'erreur serait prématuré.

Pour les mots de passe et les numéros de téléphone, on utilise des expressions régulières personnalisées ou des bibliothèques spécialisées. Par exemple, pour vérifier la complexité d'un mot de passe, vous pouvez compter le nombre de chiffres, de lettres majuscules et minuscules. TextWatcher permet de mettre à jour l'indicateur de force du mot de passe en temps réel, ce qui affecte positivement la conversion d'inscription.

Erreurs courantes lors du travail avec TextWatcher

La première erreur et la plus critique est l'appel récursif. Si vous modifiez le texte du même EditText dans afterTextChanged (via s.clear(), s.append() ou s.insert()), TextWatcher se déclenchera à nouveau. Cela crée une boucle infinie qui se termine par StackOverflowError. La solution est d'utiliser un verrou indicateur isUpdating ou de vérifier si le texte a réellement changé.

Le deuxième problème courant est la fuite de mémoire. TextWatcher maintient une référence implicite à l'Activity ou au Fragment via une classe anonyme. Si le listener n'est pas supprimé lors de la destruction de la Vue, le ramasse-miettes ne peut pas libérer la mémoire. La solution est d'utiliser des composants de cycle de vie ou d'appeler explicitement removeTextChangedListener dans onDestroyView.

La troisième erreur est l'utilisation de la mauvaise méthode. Certains développeurs effectuent la validation finale dans onTextChanged, sans attendre afterTextChanged. Dans onTextChanged, le texte n'est pas encore complètement mis à jour, et la lecture de la valeur finale peut renvoyer des données incorrectes. La bonne approche est que toute la logique de lecture et de vérification du texte final doit être dans afterTextChanged.

MéthodeMoment d'appelObjectifPeut-on lire le texte final ?
beforeTextChangedAvant la modificationSauvegarder l'état précédentOui
onTextChangedPendant la modificationJournalisation, animationNon
afterTextChangedAprès la modificationValidation, comptage, mise à jour UIOui

La quatrième erreur est l'ajout multiple de TextWatcher. Si addTextChangedListener est appelé plusieurs fois pour le même EditText, tous les listeners traiteront la même modification. Dans les formulaires avec ajout dynamique de Vues, cela conduit à des vérifications en double et à un comportement imprévisible. Vérifiez toujours si le listener a déjà été ajouté, ou utilisez une seule instance.

Foire aux questions

Quelle est la différence entre onTextChanged et afterTextChanged ?

OnTextChanged est appelé au moment de la modification du texte, lorsque les nouveaux caractères n'ont pas encore été ajoutés. Cette méthode convient à l'animation et à la journalisation. AfterTextChanged est appelé après l'application complète des modifications et donne accès au texte final via le paramètre Editable. Pour la validation et la lecture de valeurs, utilisez afterTextChanged.

Comment éviter l'appel récursif de TextWatcher ?

Utilisez un verrou indicateur de type Boolean, qui est défini sur true avant de modifier le texte dans afterTextChanged. Vérifiez l'indicateur au début de la méthode : si true — quittez. Alternativement, comparez les valeurs anciennes et nouvelles et ne modifiez le texte qu'en cas de différence réelle.

Faut-il supprimer TextWatcher lors de la destruction d'une Activity ?

Oui, absolument. La classe anonyme TextWatcher maintient une référence à l'Activity via une fermeture. Si le listener n'est pas supprimé, l'Activity ne peut pas être collectée par le ramasse-miettes. Appelez toujours removeTextChangedListener dans onDestroyView pour Fragment ou onDestroy pour Activity.

Peut-on utiliser TextWatcher dans RecyclerView ?

Oui, mais avec prudence. Dans RecyclerView, les ViewHolders sont réutilisés et un TextWatcher d'une position précédente peut rester actif. Supprimez toujours l'ancien TextWatcher avant d'en définir un nouveau dans la méthode onBindViewHolder. Utilisez des balises ou des champs séparés du ViewHolder pour stocker la référence au listener.

Quelle méthode est la meilleure pour la recherche avec autocomplétion ?

Pour un champ de recherche, utilisez afterTextChanged combiné avec debounce (délai). Implémentez une minuterie de 300-500 ms qui se réinitialise à chaque nouvelle modification de texte. Cela évite d'envoyer une requête au serveur à chaque frappe de touche et réduit la charge de l'API.

Résumé

  • TextWatcher est une interface Android pour suivre les modifications de texte dans EditText et TextView, implémentant trois méthodes de rappel.
  • La méthode afterTextChanged est le choix optimal pour la validation et la lecture du texte final après modifications.
  • L'appel récursif est le principal danger de TextWatcher, évité par un verrou indicateur.
  • La suppression du listener est obligatoire pour éviter les fuites de mémoire lors de la destruction d'une Activity ou d'un Fragment.
  • La validation en temps réel avec TextWatcher améliore l'UX et permet d'afficher les erreurs instantanément.
  • Debounce est nécessaire lors de l'implémentation de la recherche et de l'autocomplétion pour réduire la charge du serveur.
  • Choisir la bonne méthode est la clé d'un fonctionnement stable : beforeTextChanged pour sauvegarder l'état, onTextChanged pour les logs, afterTextChanged pour la vérification finale.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi