Posiziona il cursore alla fine del testo in EditText


883

Sto cambiando il valore di un EditTexton keyListener.

Ma quando cambio il testo il cursore si sposta all'inizio del EditText. Ho bisogno che il cursore sia alla fine del testo.

Come spostare il cursore alla fine del testo in a EditText.


3
Mi sono imbattuto nello stesso problema. Ma quello che mi sono chiesto meglio è perché questo sta accadendo, in modo da poter risolvere il problema prima invece di dover spostare il cursore da solo.
Kaneda,

3
@kaneda Sono pienamente d'accordo, tuttavia sarebbe stato utile se tu avessi aggiunto la soluzione effettiva.
AgentKnopf,

1
@Zainodis Era solo un pensiero. Come ho detto, ho riscontrato lo stesso problema, il che non significa necessariamente che ho trovato la soluzione. Nel mio caso ho avuto il problema con la EditTexts come elementi di a ListView. Per quanto riguarda la sperimentazione, ho apportato alcune modifiche al ListViewcodice sorgente stesso, che è una bestia piuttosto complessa, e testato sull'emulatore. Era correlato alla gestione del controllo della messa a fuoco effettuata dal componente. Quindi ovviamente non è una soluzione che potrei dare per aiutare il nostro amico. :)
Kaneda,


Questo non funziona all'interno del OnFocusChangedcallback. La soluzione è quella di mettere setSelection all'interno di un file eseguibile ed eseguirlo sul thread principale. Controlla qui stackoverflow.com/a/32156989/4514796
Ali Nem

Risposte:


1320

Prova questo:

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

15
Questo non funziona nel mio caso. Il metodo setSelection () sembra non avere alcun effetto. La mia vista EditText contiene ImageSpans. C'è qualche altro tipo di soluzione?
toobsco42

@marqss, ho avuto lo stesso problema e ha funzionato perfettamente per me. Stavo usando EditText in una finestra di dialogo e pre-popolando il testo dalla schermata principale. Quando ciò accade, il cursore si posizionava all'inizio e non alla fine, ma dopo aver provato il tuo suggerimento, tutto andava bene, come volevo. grazie per aver postato questo.
Vincy,

4
Ehi @Mullay, ora lo sto gestendo sovrascrivendo il onSelectionChanged()metodo di una 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
Potrebbe essere necessario utilizzare et.post (nuovo Runnable ({... et.setSel ... per entrare in coda. Questo perché Android aspetta di fare alcune cose di layout fino a un momento migliore pubblicando quindi se provi a impostareSelection prima che il sistema sia finito annullerà il tuo lavoro.
MinceMan

1
Funziona qui, grazie per la risposta, ma dovresti fare così: editText.setText (s); editText.setSelection (editText.getText () lunghezza ().); // dopo setText
smileVann

224

Esiste una funzione chiamata append per ediitext che aggiunge il valore di stringa al valore edittext corrente e posiziona il cursore alla fine del valore. Puoi avere il valore stringa come il valore ediitext corrente stesso e chiamare append ();

myedittext.append("current_this_edittext_string"); 

1
Se hai già del testo nel tuo EditText, scrivimyedittext.append("");
ymerdrengene il

4
@ymerdrengene solo l'applicazione myedittext.append("");non ha funzionato per me!
Chintan Shah,

4
Questo è perfetto perché sostituisce semplicemente la riga di codice che avevo. Stavo usando edittextfield.setText e l'ho appena scambiato per aggiungere. Molto semplice.
theblitz,

Dipende dall'uso se funziona o no. Per me no. L'utilizzo Selectionè il modo corretto di raggiungere tale IMO.
sud007,

140

Kotlin :

posizionare il cursore sulla posizione iniziale :

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

imposta il cursore alla fine di EditText :

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

Sotto il codice si trova il cursore dopo il secondo carattere:

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

JAVA :

posizionare il cursore sulla posizione iniziale :

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

imposta il cursore alla fine di EditText :

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

Sotto il codice si trova il cursore dopo il secondo carattere:

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

1
Potrebbe sostituire findViewById(R.id.edittext_id) as EditTextcon findViewById<EditText>(R.id.edittext_id)o semplicemente evitare il casting se si utilizzaAPI 26+
Evin1_

97

Se hai chiamato setTextprima e il nuovo testo non ha ricevuto la fase di layout chiama setSelectionin un runnable separato attivato da View.post(Runnable)(ripubblicare da questo argomento).

Quindi, per me questo codice funziona:

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

Modifica il 16/05/2019: in questo momento sto usando l'estensione Kotlin per questo:

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

e quindi - editText.placeCursorToEnd ().


Grazie, ha funzionato davvero per me. Stavo cercando di chiamare setSelection ma non funzionerà. Nel mio caso, stavo cercando di impostare un prefisso fisso per modificare il testo, quindi dopo aver impostato il prefisso, avevo bisogno di impostare il cursore alla fine del prefisso in modo che l'utente potesse inserire i dati dopo il prefisso. Dal momento che stavo facendo setSelection nel costruttore di un TextWatcher, potrebbe essere per questo che non ha funzionato. Ma la tua soluzione ha funzionato alla grande!
Wand Maker,

Sto usando questo metodo post nel mio metodo Clickablespan di MultiAutoCompleteTextView e funziona ..... Voglio che il cursore si sposti alla fine una volta che si fa clic sull'icona di eliminazione nell'intervallo di testo ... Funziona in tutti gli ultimi cellulari Android. ..ma nelle vecchie versioni ci vuole del tempo dopo il primo clic ... tutti i miei altri articoli non diventano cliccabili ... qualche indizio ??
VijayRaj,

1
Non so perché, ma questo è l'unico che funziona per me! Il mio testo di modifica ha un ascoltatore modificato focus / testo ed è racchiuso in un TextInputLayout. Una di quelle cose è rovinare tutto.
Daniel Wilson,

42

Puoi anche posizionare il cursore alla fine del testo nella EditTextvista in questo modo:

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

Questa è un'altra possibile soluzione:

et.append("");

Prova questa soluzione se non funziona per qualsiasi 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);

Funziona bene per me!


12

Nel mio caso ho creato il seguente kotlin ext. può essere utile a qualcuno

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

Quindi utilizzare come segue

mEditText.focus()

12

Se il tuo EditText non è chiaro:

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

o

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

12

Dovresti essere in grado di raggiungerlo con l'aiuto del EditText'smetodo setSelection(), vedi qui


10

penso che questo possa raggiungere quello che vuoi.

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

Se le mie osservazioni sono corrette, viene generata un'istanza di android.widget.TextView $ IClipboardDataPasteEventImpl per ciascun widget. Ho finito con tonnellate di loro. Apparentemente alla fine vengono ripuliti, ma sembrano aumentare il consumo di memoria. Ho avuto 12 istanze di una finestra di dialogo, è solo il dominatore (che cosa lo tiene in vita) è l'istanza sopra menzionata.
AgentKnopf,

Posizionando quel pezzo di codice nella posizione appropriata nel codice (dove stai aggiungendo testo direttamente a EText). Grazie!
sud007,

9

La domanda è vecchia e ha una risposta, ma penso che potrebbe essere utile avere questa risposta se si desidera utilizzare gli strumenti DataBinding appena rilasciati per Android, basta impostarlo nel proprio XML:

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

6

inserisci qui la descrizione dell'immagine

Ciao prova questo

 <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 pointCursore


5

Se si desidera selezionare tutto il testo e inserire solo il nuovo testo anziché quello vecchio, è possibile utilizzare

    android:selectAllOnFocus="true"

5

Questo funziona

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

5

editText.setSelectionè la magia qui. Fondamentalmente la selezione consente di posizionare il cursore in qualsiasi posizione desiderata.

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

Ciò posiziona il cursore alla fine di EditText. Fondamentalmente editText.getText().length()ti dà la lunghezza del testo. Quindi usi setSelectioncon lunghezza.

editText.setSelection(0);

Serve per impostare il cursore sulla posizione iniziale (0).


4

Tutti gli altri codici che ho testato non hanno funzionato bene a causa del fatto che l'utente poteva ancora posizionare il cursore / cursore ovunque nel mezzo della stringa (es .: 12 | 3.00 - dove | è il cursore). La mia soluzione posiziona sempre il cursore alla fine della stringa ogni volta che si verifica il tocco su EditText.

La soluzione definitiva è:

// 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 / amount = "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) {

            }
        });

Spero che sia d'aiuto!


3

Per ViewModel, LiveData e Data binding

Avevo bisogno di questa funzionalità EditTextcon il supporto multilinea nella mia app per le note. Volevo il cursore alla fine del testo quando l'utente naviga verso il frammento che ha il testo della nota.

La soluzione suggerita da djleop si avvicina. Ma il problema è che, se l'utente posiziona il cursore da qualche parte nel mezzo del testo per la modifica e inizia a digitare, il cursore salta di nuovo alla fine del testo. Questo è successo perché ilLiveData emetteva il nuovo valore e il cursore saltava nuovamente alla fine del testo, facendo sì che l'utente non fosse in grado di modificare il testo da qualche parte nel mezzo.

Per risolverlo, lo uso MediatorLiveDatae lo assegno Stringsolo una volta usando una bandiera. Ciò farà sì che LiveData legga il valore una sola volta, ovvero quando l'utente passa al frammento. Dopodiché l'utente può posizionare il cursore in qualsiasi punto del punto in cui desidera modificare il testo.

ViewModel

private var accessedPosition: Boolean = false

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

Ecco yourObjectun altro LiveData recuperato dal database che contiene il testo String che si sta visualizzando inEditText .

Quindi associa questo MediatorLiveDataal tuo EditText usando un adattatore di rilegatura.

XML

Utilizza l'associazione dati bidirezionale per visualizzare il testo e per accettare l'inserimento del testo.

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

Adattatore vincolante

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

Event classe

La Eventclasse qui è come un SingleLiveEvent scritto da Jose Alcérreca da Google. Lo uso qui per occuparmi della rotazione dello schermo. L'uso del singolo Eventfarà in modo che il cursore non salti alla fine del testo quando l'utente sta modificando il testo da qualche parte nel mezzo e lo schermo ruota. Manterrà la stessa posizione quando lo schermo ruota.

Ecco la Eventlezione:

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
}

Questa è la soluzione che funziona per me e offre una buona esperienza utente. Spero che sia d'aiuto anche nei tuoi progetti.


Questa risposta deve essere molto in alto.
Mille

2

simile alla risposta di @Anh Duy, ma non ha funzionato per me. avevo anche bisogno che il cursore si spostasse alla fine solo quando l'utente tocca il testo di modifica ed è ancora in grado di selezionare la posizione del cursore in seguito, questo è l'unico codice che ha funzionato per me

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

Questo fa il trucco in sicurezza :

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


2

Le risposte sopra non hanno funzionato per me. Quindi ho scoperto una nuova soluzione. Questo potrebbe essere utile a qualcuno. Ho usato l'ultima versione di Android Studio, ad esempio 3.5 alla data attuale. Forse questo potrebbe essere il motivo per cui le risposte di cui sopra non hanno mostrato alcun effetto.

CODICE:

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

Qui, il primo argomento è il valore di testo Spannable con cui si desidera giocare, mentre il secondo argomento è il valore dell'indice. Poiché, vogliamo il cursore alla fine del testo, abbiamo preso getText (). Length () che restituisce la lunghezza del testo


1
Il piacere è tutto mio! Buona programmazione!
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) {

    }
}

Usa questo CustomEditText nel tuo file XML, funzionerà. Ho provato questo e funziona per me.


1

Se si desidera posizionare il cursore alla fine del testo nella vista Modifica testo

 EditText rename;
 String title = "title_goes_here";
 int counts = (int) title.length();
 rename.setSelection(counts);
 rename.setText(title);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.