Pourquoi le curseur dans EditText est-il un casse-tête pour les débutants ?
\nImaginez : vous développez une application de notes ou de chat. L'utilisateur ouvre une note existante, commence à taper — et soudain, le nouveau texte s'insère au début ou au milieu de la ligne. Une situation familière ? C'est l'un de ces petits problèmes, incroyablement agaçants, que rencontre toute personne qui commence à apprendre le développement Android en Kotlin.
\nSur Stack Overflow, la question « Place cursor at the end of text in EditText » a rassemblé des milliers de vues et des dizaines de réponses. Pourquoi ? Parce qu'il n'existe pas de méthode intuitive pour « simplement placer le curseur à la fin » dans le SDK Android. Il faut connaître quelques astuces. Aujourd'hui, nous allons les décortiquer une fois pour toutes — simplement, clairement et avec des exemples de code.
\nD'ailleurs, si vous développez non seulement pour Android, mais aussi, par exemple, un backend en Python — sur notre site PythonLib, vous trouverez de nombreuses ressources pour démarrer. Mais aujourd'hui, nous parlons de développement mobile.
\n\nLa solution classique : setSelection()
\nL'outil principal pour gérer le curseur dans EditText est la méthode setSelection(). Elle prend en paramètre l'indice de la position où déplacer le curseur. Mais pour placer le curseur tout à la fin, nous devons d'abord connaître la longueur du texte.
// Méthode simple : on prend la longueur du texte et on la passe à setSelection\neditText.setText("Bonjour le monde !")\neditText.setSelection(editText.text.length)\n\nEt voilà ! editText.text.length retourne le nombre de caractères. On passe ce nombre à setSelection() — et le curseur se place après le dernier caractère.
Mais il y a un piège : quand appeler cette méthode ?
\nLes débutants écrivent souvent ce code juste après setText() — et sont surpris que cela ne fonctionne pas. Le problème est que EditText peut ne pas encore avoir eu le temps de se mettre à jour. C'est particulièrement vrai si vous définissez le texte par programmation dans un fragment ou une activité.
La meilleure solution est d'utiliser post() ou un écouteur onTextChanged. Voici un exemple avec post() — cela garantit que le code s'exécute après que la View soit prête :
editText.setText("Un long texte à éditer")\neditText.post {\n editText.setSelection(editText.text.length)\n}\n\nMaintenant, le curseur sera bien à la fin. Cette méthode est votre sauveur dans 90% des cas.
\n\nEt si le texte change dynamiquement ?
\nSupposons que vous développiez un champ de recherche qui suggère automatiquement des termes. Ou un éditeur où l'utilisateur peut insérer des modèles. Dans ces situations, vous devez placer le curseur à la fin à chaque fois que le texte change par programmation.
\nUtilisez TextWatcher ou, plus simplement, appelez setSelection() après chaque modification :
fun appendText(newText: String) {\n val currentText = editText.text.toString()\n editText.setText(currentText + newText)\n editText.setSelection(editText.text.length)\n}\n\nCe code ajoute d'abord le nouveau texte à l'existant, puis déplace le curseur à la fin. Cela fonctionne sans faille.
\n\nAstuce pour les expérimentés : Editable et Spannable
\nSi vous travaillez directement avec Editable (par exemple, en l'obtenant via editText.text), vous pouvez utiliser SpannableStringBuilder et la méthode setSpan(). Mais pour la tâche de base « curseur à la fin », c'est excessif. Souvenez-vous : post { setSelection(length) } est votre technique de base.
Pourquoi cela ne fonctionne-t-il pas dans les dialogues et les fragments ?
\nUne autre question fréquente sur Stack Overflow. Si votre EditText se trouve à l'intérieur d'un AlertDialog ou d'un BottomSheetDialogFragment, le code peut ne pas fonctionner car la View n'est pas encore attachée à la fenêtre.
La solution est d'utiliser onResume() ou onWindowFocusChanged(). En