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.