Coloque o cursor no final do texto em EditText


883

Eu estou mudando o valor de um EditTextno keyListener.

Mas quando eu mudo o texto, o cursor está se movendo para o início do EditText. Eu preciso que o cursor esteja no final do texto.

Como mover o cursor para o final do texto em a EditText.


3
Me deparei com o mesmo problema. Mas o que me perguntei melhor é por que isso está acontecendo, para que eu pudesse resolver o problema antes, em vez de ter que mudar o cursor por conta própria.
— kaneda

3
@kaneda Eu concordo totalmente, no entanto, teria sido útil se você tivesse adicionado a solução real.
— AgentKnopf

1
@ Zainodis Foi apenas um pensamento. Como eu disse, me deparei com o mesmo problema, o que não significa necessariamente que eu encontrei a solução. No meu caso, tive o problema com os EditTexts como itens de a ListView. Quanto à experimentação, fiz algumas alterações no ListViewpróprio código-fonte, que é uma fera bastante complexa, e testei no emulador. Estava relacionado ao gerenciamento de controle de foco feito pelo componente. Portanto, é claro que não é uma solução que eu poderia dar para ajudar nosso amigo. :)
— kaneda


Isso não funciona dentro do OnFocusChangedretorno de chamada. A solução é colocar setSelection dentro de um executável e executá-lo no thread principal. Confira aqui stackoverflow.com/a/32156989/4514796
— Ali Nem

Respostas:


1319

Tente o seguinte:

EditText et = (EditText)findViewById(R.id.inbox);
et.setSelection(et.getText().length());

15
Isso não funciona no meu caso. O método setSelection () parece não ter efeito. Minha visualização EditText contém ImageSpans. Existe algum outro tipo de solução alternativa?
— toobsco42

@ marqss, tive o mesmo problema e funcionou perfeitamente para mim. Eu estava usando o EditText em uma caixa de diálogo e preenchendo previamente o texto na tela principal. Quando isso acontece, o cursor ficou no começo e não no final, mas depois que tentei sua sugestão, tudo estava bem, do jeito que eu queria. Obrigado por postar isso.
— Vincy

4
Ei @Mullay, agora estou lidando com isso, substituindo o onSelectionChanged()método de uma EditTextclasse: public void onSelectionChanged(int start, int end) { CharSequence text = getText(); if (text != null) { if (start != text.length() || end != text.length()) { setSelection(text.length(), text.length()); return; } } super.onSelectionChanged(start, end); }
— toobsco42

19
Você pode ter que usar et.post (novo Runnable ({... et.setSel ... para entrar na fila. Isso ocorre porque o Android espera para fazer algumas coisas de layout até um momento melhor postando isso, se você tentar setSelection antes que o sistema termine, ele desfará seu trabalho.
— MinceMan

1
Funciona aqui, obrigado pela sua resposta. Mas você deve fazer assim: editText.setText (s); editText.setSelection (editText.getText (). length ()); // após
— setText

224

Existe uma função chamada append para ediitext que acrescenta o valor da string ao valor atual do edittext e coloca o cursor no final do valor. Você pode ter o valor da string como o próprio valor atual do ediitext e chamar append ();

myedittext.append("current_this_edittext_string"); 

1
Se você já tem texto no EditText, basta escrevermyedittext.append("");
— ymerdrengene

4
@ymerdrengene acabou de aplicar myedittext.append("");não funcionou para mim!
— precisa

4
Isso é perfeito porque simplesmente substitui a linha de código que eu tinha. Estava usando o edittextfield.setText e apenas trocou por acréscimo. Muito simples.
— theblitz 22/02

Depende do uso, se isso funciona ou não. Para mim não. O uso Selectioné a maneira correta de atingir esse IMO.
— sud007

140

Kotlin :

coloque o cursor na posição inicial :

val editText = findViewById(R.id.edittext_id) as EditText
editText.setSelection(0)

defina o cursor para o final do EditText :

val editText = findViewById(R.id.edittext_id) as EditText
editText.setSelection(editText.text.length)

Abaixo, o código deve colocar o cursor após o segundo caractere:

val editText = findViewById(R.id.edittext_id) as EditText
editText.setSelection(2)

JAVA :

coloque o cursor na posição inicial :

 EditText editText = (EditText)findViewById(R.id.edittext_id);
 editText.setSelection(0);

defina o cursor para o final do EditText :

EditText editText = (EditText)findViewById(R.id.edittext_id);
editText.setSelection(editText.getText().length());

Abaixo, o código deve colocar o cursor após o segundo caractere:

EditText editText = (EditText)findViewById(R.id.edittext_id);
editText.setSelection(2);

1
Poderia substituir findViewById(R.id.edittext_id) as EditTextcom findViewById<EditText>(R.id.edittext_id)ou apenas evitar a fundição se estiver usandoAPI 26+
— Evin1_

97

Se você telefonou setTextantes e o novo texto não recebeu a chamada da fase de layout setSelectionem um executável separado acionado por View.post(Runnable)(repost deste tópico).

Então, para mim, esse código funciona:

editText.setText("text");
editText.post(new Runnable() {
         @Override
         public void run() {
             editText.setSelection(editText.getText().length());
         }
});

Editar 16/05/2019: No momento, estou usando a extensão Kotlin para isso:

fun EditText.placeCursorToEnd() {
    this.setSelection(this.text.length)
}

e depois - editText.placeCursorToEnd ().


Graças isso realmente funcionou para mim. Eu estava tentando chamar setSelection, mas não funcionou. No meu caso, eu estava tentando definir um prefixo fixo para editar o texto e, depois de definir o prefixo, precisei definir o cursor no final do prefixo para que o usuário pudesse inserir dados após o prefixo. Desde que eu estava fazendo setSelection no construtor de um TextWatcher, pode ser por isso que não funcionou. Mas sua solução funcionou muito bem!
— 214132Página

Estou usando esse método de postagem no método Clickablespan do meu MultiAutoCompleteTextView e funciona ... Quero que o cursor se mova no final depois que o ícone de exclusão no período de texto for clicado ... Ele funciona em todos os celulares Android mais recentes. ..mas nas versões antigas demora algum tempo após o primeiro clique ... todos os meus outros itens não se tornam clicáveis ​​... alguma pista ??
— precisa saber é o seguinte

1
Não sei por que, mas este é o único que funciona para mim! Meu texto de edição possui um ouvinte alterado de foco / texto e está envolvido em um TextInputLayout. Uma dessas coisas é estragar tudo.
— Daniel Wilson

42

Você também pode colocar o cursor no final do texto na EditTextexibição da seguinte maneira:

EditText et = (EditText)findViewById(R.id.textview);
int textLength = et.getText().length();
et.setSelection(textLength, textLength);

27
editText.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        editText.setSelection(editText.getText().length());
        return false;
    }
});

21

Essa é outra solução possível:

et.append("");

Apenas tente esta solução se não funcionar por qualquer motivo:

et.setSelection(et.getText().length());

12
/**
 * Set cursor to end of text in edittext when user clicks Next on Keyboard.
 */
View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View view, boolean b) {
        if (b) {
            ((EditText) view).setSelection(((EditText) view).getText().length());
        }
    }
};

mEditFirstName.setOnFocusChangeListener(onFocusChangeListener); 
mEditLastName.setOnFocusChangeListener(onFocusChangeListener);

Funciona bem para mim!


12

No meu caso, criei o seguinte kotlin ext. função, pode ser útil para alguém

 private fun EditText.focus(){
        requestFocus()
        setSelection(length())
    }

Em seguida, use da seguinte maneira

mEditText.focus()

12

Se o seu EditText não estiver claro:

editText.setText("");
editText.append("New text");

ou

editText.setText(null);
editText.append("New text");

12

Você deve conseguir isso com a ajuda do EditText'smétodo setSelection(), veja aqui


10

Eu acho que isso pode conseguir o que você quer.

 Editable etext = mSubjectTextEditor.getText();
 Selection.setSelection(etext, etext.length());

Se minhas observações estiverem corretas, isso gerará uma instância de android.widget.TextView $ IClipboardDataPasteEventImpl para cada widget. Acabei com toneladas deles. Aparentemente, eles acabam sendo limpos, mas parecem aumentar o consumo de memória. Eu tive 12 instâncias de um diálogo, é apenas o dominador (o que o mantém vivo) sendo o exemplo acima mencionado.
— AgentKnopf

Colocando esse trecho de código na posição apropriada no código (em que você anexa o texto diretamente ao EText). Obrigado!
— sud007

9

A pergunta é antiga e respondida, mas acho que pode ser útil ter essa resposta se você quiser usar as ferramentas DataBinding recém-lançadas para Android, basta definir isso em seu XML:

<data>
    <variable name="stringValue" type="String"/>
</data>
...
<EditText
        ...
        android:text="@={stringValue}"
        android:selection="@{stringValue.length()}"
        ...
/>

6

insira a descrição da imagem aqui

Olá, tente isso

 <EditText
       android:id="@+id/edt_text"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="Hello World!"
       android:cursorVisible="true"/>

EditText editText = findViewById(R.id.editText); editText.setSelection(editText.getText().length()); // End pointCursor


5

Se você quiser selecionar todo o texto e apenas inserir um novo texto em vez do antigo, use

    android:selectAllOnFocus="true"

5

Isso funciona

Editable etext = edittext.getText();
Selection.setSelection(etext,edittext.getText().toString().length());

5

editText.setSelectioné a mágica aqui. Basicamente, a seleção permite colocar o cursor em qualquer posição desejada.

EditText editText = findViewById(R.id.editText);
editText.setSelection(editText.getText().length());

Isso coloca o cursor no final do EditText. Basicamente, editText.getText().length()fornece o tamanho do texto. Então você usa setSelectioncom comprimento.

editText.setSelection(0);

É para definir o cursor na posição inicial (0).


4

Todos os outros códigos que testei não funcionaram bem devido ao fato de o usuário ainda poder colocar o cursor / cursor em qualquer lugar no meio da string (por exemplo: 12 | 3.00 - onde | é o cursor). Minha solução sempre coloca o cursor no final da string sempre que o toque ocorre no EditText.

A solução final é:

// For a EditText like:
<EditText
                android:id="@+id/EditTextAmount"
                android:layout_height="wrap_content"
                android:layout_width="fill_parent"
                android:hint="@string/amount"
                android:layout_weight="1"
                android:text="@string/zero_value"
                android:inputType="text|numberDecimal"
                android:maxLength="13"/>

@ string / quantidade = "0,00" @ string / zero_value = "0,00"

// Create a Static boolean flag
private static boolean returnNext; 


// Set caret/cursor to the end on focus change
EditTextAmount.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View editText, boolean hasFocus) {
                if(hasFocus){
                    ((EditText) editText).setSelection(((EditText) editText).getText().length());
                }
            }
        });

// Create a touch listener and put caret to the end (no matter where the user touched in the middle of the string)
EditTextAmount.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View editText, MotionEvent event) {
                ((EditText) editText).onTouchEvent(event);
                ((EditText) editText).setSelection(((EditText) editText).getText().length());
                return true;
            }
        });


// Implement a Currency Mask with addTextChangedListener
EditTextAmount.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                String input = s.toString();
                String output = new String();
                String buffer = new String();
                String decimals = new String();
                String numbers = Integer.toString(Integer.parseInt(input.replaceAll("[^0-9]", "")));

                if(returnNext){
                    returnNext = false;
                    return;
                }

                returnNext = true;

                if (numbers.equals("0")){
                    output += "0.00";
                }
                else if (numbers.length() <= 2){
                    output += "0." + String.format("%02d", Integer.parseInt(numbers));
                }
                else if(numbers.length() >= 3){
                    decimals = numbers.substring(numbers.length() - 2);
                    int commaCounter = 0;
                    for(int i=numbers.length()-3; i>=0; i--){
                        if(commaCounter == 3){
                            buffer += ",";
                            commaCounter = 0;
                        }
                        buffer += numbers.charAt(i);
                        commaCounter++;
                    }
                    output = new StringBuilder(buffer).reverse().toString() + "." + decimals;
                }
                EditTextAmount.setText(output);
                EditTextAmount.setSelection(EditTextAmount.getText().length());
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                /*String input = s.toString();
                if(input.equals("0.0")){
                    EditTextAmount.setText("0.00");
                    EditTextAmount.setSelection(EditTextAmount.getText().length());
                    return;
                }*/
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

Espero que ajude!


3

Para ViewModel, LiveData e ligação de dados

Eu precisava dessa funcionalidade para EditText suporte multilinhas no meu aplicativo de anotações. Eu queria o cursor no final do texto quando o usuário navega para o fragmento que possui o texto da nota.

A solução sugerida pelo djleop chega perto. Mas o problema é que, se o usuário colocar o cursor em algum lugar no meio do texto para edição e começar a digitar, o cursor saltará para o final do texto novamente. Isso aconteceu porque oLiveData comando emitia o novo valor e o cursor pularia novamente para o final do texto, resultando no usuário não capaz de editar o texto em algum lugar no meio.

Para resolver isso, eu uso MediatorLiveDatae atribuo o comprimento Stringapenas uma vez usando um sinalizador. Isso fará com que o LiveData leia o valor apenas uma vez, ou seja, quando o usuário navega para o fragmento. Depois disso, o usuário pode colocar o cursor em qualquer lugar que desejar editar o texto lá.

ViewModel

private var accessedPosition: Boolean = false

val cursorPosition = MediatorLiveData<Event<Int>>().apply {
    addSource(yourObject) { value ->
        if(!accessedPosition) {
            setValue(Event(yourObject.note.length))
            accessedPosition = true
        }
    }
}

Aqui yourObjectestá outro LiveData recuperado do banco de dados que contém o texto String que você está exibindo no EditText.

Em seguida, vincule isso MediatorLiveDataao seu EditText usando o adaptador de ligação.

XML

Utiliza ligação de dados bidirecional para exibir texto e também para aceitar a entrada de texto.

<!-- android:text must be placed before cursorPosition otherwise we'll get IndexOutOfBounds exception-->
<EditText
    android:text="@={viewModel.noteText}"
    cursorPosition="@{viewModel.cursorPosition}" />

Adaptador de ligação

@BindingAdapter("cursorPosition")
fun bindCursorPosition(editText: EditText, event: Event<Int>?) {
    event?.getContentIfNotHandled()?.let { editText.setSelection(it) }
}

Event classe

A Eventclasse aqui é como um SingleLiveEvent escrito por Jose Alcérreca do Google. Eu o uso aqui para cuidar da rotação da tela. O uso do single Eventgarantirá que o cursor não vá para o final do texto quando o usuário estiver editando o texto em algum lugar no meio e a tela girar. Ele manterá a mesma posição quando a tela girar.

Aqui está a Eventturma:

open class Event<out T>(private val content: T) {

    var hasBeenHandled = false
        private set // Allow external read but not write

    /**
     * Returns the content and prevents its use again.
     */
    fun getContentIfNotHandled(): T? {
        return if (hasBeenHandled) {
            null
        } else {
            hasBeenHandled = true
            content
        }
    }

    /**
     * Returns the content, even if it's already been handled.
     */
    fun peekContent(): T = content
}

Esta é a solução que funciona para mim e fornece uma boa experiência do usuário. Espero que ajude em seus projetos também.


Essa resposta precisa estar bem adiantada. Muito obrigado
— Abdul Rahman Shamair

2

semelhante à resposta de @Anh Duy, mas não funcionou para mim. Eu também precisava que o cursor se movesse até o fim somente quando o usuário tocar no texto de edição e ainda conseguir selecionar a posição do cursor depois, esse é o único código que funcionou para mim

boolean textFocus = false; //define somewhere globally in the class

//in onFinishInflate() or somewhere
editText.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {

        editText.onTouchEvent(event);

        if(!textFocus) {
            editText.setSelection(editText.getText().length());
            textFocus = true;
        }

        return true;
    }
});

editText.setOnFocusChangeListener(new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        textFocus = false;
    }
});

2

Isso faz o truque com segurança :

    editText.setText("");
    if (!TextUtils.isEmpty(text)) {
        editText.append(text);
    }


2

As respostas acima não funcionaram para mim. Então eu descobri uma nova solução. Isso talvez seja útil para alguém. Estou usando a versão mais recente do Android Studio, ou seja, 3.5, conforme a data atual. Talvez essa seja a razão pelas quais as respostas acima não tenham mostrado efeito.

CÓDIGO:

EditText available_seats = findViewById(R.id.available_seats);
Selection.setSelection(available_seats.getText(),available_seats.getText().length());

Aqui, o primeiro argumento é o valor do texto Spannable que você deseja reproduzir, enquanto o segundo argumento é o valor do índice. Como queremos o cursor no final do texto, pegamos getText (). Length () que retorna o tamanho do texto


1
O prazer é meu! Feliz codificação!
— Prajwal W

1
public class CustomEditText extends EditText {
    public CustomEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomEditText(Context context) {
        super(context);
    }

    public CustomEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }


    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        this.setSelection(this.getText().length());
    }

    @Override
    protected void onSelectionChanged(int selStart, int selEnd) {

    }
}

Use este CustomEditText no seu arquivo XML, isso funcionará. Eu testei isso e está funcionando para mim.


1

Se você deseja colocar o cursor no final do texto na visualização EditText

 EditText rename;
 String title = "title_goes_here";
 int counts = (int) title.length();
 rename.setSelection(counts);
 rename.setText(title);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.