¿Por qué el cursor en EditText es un dolor de cabeza para principiantes?
\nImagina: estás escribiendo una aplicación para notas o chat. El usuario abre una nota existente, comienza a escribir y, de repente, el nuevo texto se inserta al inicio o en medio de la línea. ¿Te suena familiar? Este es uno de esos pequeños problemas increíblemente molestos que enfrenta todo aquel que comienza a aprender desarrollo Android con Kotlin.
\nEn Stack Overflow, la pregunta «Place cursor at the end of text in EditText» ha acumulado miles de visitas y decenas de respuestas. ¿Por qué? Porque no hay una forma intuitiva de «simplemente colocar el cursor al final» en el SDK de Android. Necesitas conocer algunos trucos. Hoy los analizaremos de una vez por todas: de forma simple, clara y con ejemplos de código.
\nPor cierto, si no solo desarrollas para Android, sino también, por ejemplo, backend en Python, en nuestro sitio PythonLib encontrarás muchos materiales para empezar. Pero hoy hablamos de desarrollo móvil.
\n\nSolución clásica: setSelection()
\nLa herramienta principal para controlar el cursor en EditText es el método setSelection(). Este acepta el índice de la posición a la que deseas mover el cursor. Pero para colocar el cursor al final, primero necesitamos conocer la longitud del texto.
// Forma simple: tomamos la longitud del texto y la pasamos a setSelection\neditText.setText("¡Hola, mundo!")\neditText.setSelection(editText.text.length)\n\n¡Eso es todo! editText.text.length devuelve la cantidad de caracteres. Pasamos este número a setSelection() y el cursor se coloca después del último carácter.
Pero hay un truco: ¿cuándo llamarlo?
\nLos principiantes a menudo escriben este código justo después de setText() y se sorprenden de que no funcione. El problema es que EditText puede no haberse actualizado aún. Esto es especialmente relevante si estableces el texto programáticamente en un fragmento o actividad.
La mejor solución es usar post() o el listener onTextChanged. Aquí tienes un ejemplo con post() que garantiza que el código se ejecute después de que la View esté lista:
editText.setText("Texto largo que necesita ser editado")\neditText.post {\n editText.setSelection(editText.text.length)\n}\n\nAhora el cursor estará definitivamente al final. Este método es tu salvador en el 90% de los casos.
\n\n¿Y si el texto cambia dinámicamente?
\nSupongamos que estás escribiendo un campo de búsqueda que autocompleta sugerencias. O un editor donde el usuario puede insertar plantillas. En estas situaciones, necesitas colocar el cursor al final cada vez que el texto cambie programáticamente.
\nUsa TextWatcher o, más simple, simplemente llama a setSelection() después de cada cambio:
fun appendText(newText: String) {\n val currentText = editText.text.toString()\n editText.setText(currentText + newText)\n editText.setSelection(editText.text.length)\n}\n\nEste código primero agrega el nuevo texto al existente y luego mueve el cursor al final. Funciona sin problemas.
\n\nTruco para avanzados: Editable y Spannable
\nSi trabajas directamente con Editable (por ejemplo, lo obtienes de editText.text), puedes usar SpannableStringBuilder y el método setSpan(). Pero para la tarea básica de «cursor al final», esto es excesivo. Recuerda: post { setSelection(length) } es tu técnica básica.
¿Por qué no funciona en diálogos y fragmentos?
\nOtra pregunta frecuente en Stack Overflow. Si tu EditText está dentro de un AlertDialog o BottomSheetDialogFragment, el código puede no funcionar porque la View aún no está adjunta a la ventana.
La solución es usar onResume() o onWindowFocusChanged(). En