Por que o cursor no EditText é uma dor de cabeça para iniciantes?
\nImagine: você está escrevendo um aplicativo de anotações ou chat. O usuário abre uma nota existente, começa a digitar — e de repente o novo texto é inserido no início ou no meio da linha. Situação familiar? Este é um daqueles problemas pequenos, mas extremamente irritantes, que todo mundo que começa a estudar desenvolvimento Android em Kotlin enfrenta.
\nNo Stack Overflow, a pergunta «Place cursor at the end of text in EditText» acumulou milhares de visualizações e dezenas de respostas. Por quê? Porque não existe uma maneira intuitiva de "apenas colocar o cursor no final" no Android SDK. É preciso conhecer alguns truques. Hoje vamos analisá-los de uma vez por todas — de forma simples, clara e com exemplos de código.
\nA propósito, se você programa não apenas para Android, mas também, por exemplo, um backend em Python — no nosso site PythonLib você encontrará muitos materiais para começar. Mas hoje estamos falando sobre desenvolvimento mobile.
\n\nSolução clássica: setSelection()
\nA principal ferramenta para controlar o cursor no EditText é o método setSelection(). Ele recebe o índice da posição para onde o cursor deve ser movido. Mas para colocar o cursor bem no final, primeiro precisamos saber o comprimento do texto.
// Maneira simples: pegar o comprimento do texto e passá-lo para setSelection\neditText.setText("Olá, mundo!")\neditText.setSelection(editText.text.length)\n\nÉ isso! editText.text.length retorna o número de caracteres. Passamos esse número para setSelection() — e o cursor vai para depois do último caractere.
Mas há um detalhe: quando chamar?
\nIniciantes frequentemente escrevem este código logo após setText() — e se surpreendem que nada funciona. O problema é que o EditText pode ainda não ter tido tempo de ser atualizado. Isso é especialmente relevante se você está definindo o texto programaticamente em um fragmento ou activity.
A melhor solução é usar post() ou o listener onTextChanged. Aqui está um exemplo com post() — isso garante que o código será executado depois que a View estiver pronta:
editText.setText("Texto longo que precisa ser editado")\neditText.post {\n editText.setSelection(editText.text.length)\n}\n\nAgora o cursor com certeza estará no final. Este método é o seu salvador em 90% dos casos.
\n\nE se o texto muda dinamicamente?
\nSuponha que você está escrevendo um campo de busca que sugere automaticamente. Ou um editor onde o usuário pode inserir modelos. Nessas situações, você precisa colocar o cursor no final toda vez que o texto muda programaticamente.
\nUse TextWatcher ou, mais simplesmente, apenas chame setSelection() após cada alteração:
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 primeiro adiciona o novo texto ao existente e, em seguida, move o cursor para o final. Funciona perfeitamente.
\n\nDica para experientes: Editable e Spannable
\nSe você trabalha diretamente com Editable (por exemplo, obtendo-o de editText.text), pode usar SpannableStringBuilder e o método setSpan(). Mas para a tarefa básica de "cursor no final", isso é excessivo. Lembre-se: post { setSelection(length) } é a sua técnica básica.
Por que isso não funciona em diálogos e fragmentos?
\nOutra pergunta frequente no Stack Overflow. Se o seu EditText está dentro de um AlertDialog ou BottomSheetDialogFragment, o código pode não funcionar porque a View ainda não está anexada à janela.
A solução é usar onResume() ou onWindowFocusChanged(). Em