Platzieren Sie den Cursor am Ende des Textes in EditText

883

Ich ändere den Wert eines EditTextauf keyListener.

Aber wenn ich den Text ändere, bewegt sich der Cursor an den Anfang von EditText. Der Cursor muss sich am Ende des Textes befinden.

So bewegen Sie den Cursor an das Ende des Textes in a EditText.

Manu
quelle
3
Ich bin auf das gleiche Problem gestoßen. Was ich mich aber besser gefragt habe, ist, warum dies geschieht, damit ich das Problem vorher lösen kann, anstatt das Caret selbst bewegen zu müssen.
Kaneda
3
@kaneda Ich stimme vollkommen zu, aber es wäre hilfreich gewesen, wenn Sie die eigentliche Lösung hinzugefügt hätten.
AgentKnopf
1
@ Zainodis Es war nur ein Gedanke. Wie gesagt, ich bin auf dasselbe Problem gestoßen, was nicht unbedingt bedeutet, dass ich die Lösung gefunden habe. In meinem Fall hatte ich das Problem mit dem EditTexts als Artikel von a ListView. Zum Experimentieren habe ich einige Änderungen am ListViewQuellcode selbst vorgenommen, der ein ziemlich komplexes Tier ist, und am Emulator getestet. Es bezog sich auf das von der Komponente vorgenommene Fokussteuerungsmanagement. Natürlich ist es keine Lösung, die ich geben könnte, um unserem Freund zu helfen. :)
Kaneda
2
Mögliches Duplikat von Android edittext - Settextmethod Cursor Problem
AZ_
Dies funktioniert nicht innerhalb des OnFocusChangedRückrufs. Die Lösung besteht darin, setSelection in eine ausführbare Datei einzufügen und auf dem Hauptthread auszuführen. Überprüfen Sie hier stackoverflow.com/a/32156989/4514796
Ali Nem

Antworten:

1319

Versuche dies:

EditText et = (EditText)findViewById(R.id.inbox);
et.setSelection(et.getText().length());
Marqs
quelle
15
Dies funktioniert in meinem Fall nicht. Die setSelection () -Methode scheint keine Auswirkung zu haben. Meine EditText-Ansicht enthält ImageSpans. Gibt es eine andere Art von Problemumgehung?
toobsco42
@marqss, ich hatte das gleiche Problem und arbeitete perfekt für mich. Ich habe EditText in einem Dialogfeld verwendet und Text vom Hauptbildschirm vorab ausgefüllt. In diesem Fall blieb der Cursor am Anfang und nicht am Ende, aber nachdem ich Ihren Vorschlag ausprobiert hatte, ist alles in Ordnung, so wie ich es wollte. Vielen Dank für die Veröffentlichung.
Vincy
4
Hey @ Mullay, ich behandle es jetzt, indem ich die onSelectionChanged()Methode einer EditTextKlasse überschreibe : 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
Möglicherweise müssen Sie et.post (new Runnable ({... et.setSel ...) verwenden, um in die Warteschlange zu gelangen. Dies liegt daran, dass Android darauf wartet, einige Layout-Aufgaben bis zu einem besseren Zeitpunkt durch Posten zu erledigen, wenn Sie versuchen, setSelection festzulegen bevor das System fertig ist, wird es Ihre Arbeit rückgängig machen.
MinceMan
1
Es funktioniert hier, danke für Ihre Antwort. Aber Sie sollten dies wie folgt tun: editText.setText (s); editText.setSelection (editText.getText (). length ()); // nach setText
smileVann
224

Es gibt eine Funktion namens append for ediitext, die den Zeichenfolgenwert an den aktuellen edittext-Wert anfügt und den Cursor am Ende des Werts platziert. Sie können den Zeichenfolgenwert als aktuellen Ediitext-Wert selbst festlegen und append () aufrufen.

myedittext.append("current_this_edittext_string"); 
James
quelle
1
Wenn Sie bereits Text in Ihrem EditText haben, schreiben myedittext.append("");
Sie
4
@ymerdrengene nur bewerben myedittext.append("");hat bei mir nicht funktioniert!
Chintan Shah
4
Dies ist perfekt, weil es einfach die Codezeile ersetzt, die ich hatte. Ich habe edittextfield.setText verwendet und es einfach gegen Anhängen ausgetauscht. Sehr einfach.
Theblitz
Hängt von der Verwendung ab, ob das funktioniert oder nicht. Für mich war es nicht so. Die Verwendung Selectionist der richtige Weg, um diese IMO zu erreichen.
Sud007
140

Kotlin :

Stellen Sie den Cursor auf die Startposition :

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

Setzen Sie den Cursor auf das Ende des EditText :

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

Unter Code befindet sich der Cursor nach dem zweiten Zeichen:

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

JAVA :

Stellen Sie den Cursor auf die Startposition :

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

Setzen Sie den Cursor auf das Ende des EditText :

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

Unter Code befindet sich der Cursor nach dem zweiten Zeichen:

EditText editText = (EditText)findViewById(R.id.edittext_id);
editText.setSelection(2);
Mr. Vicky Patel
quelle
1
Könnte ersetzen findViewById(R.id.edittext_id) as EditTextmit findViewById<EditText>(R.id.edittext_id)oder einfach nur das Gießen vermeiden , wenn mitAPI 26+
Evin1_
97

Wenn Sie setTextzuvor angerufen haben und der neue Text keinen Layoutphasenaufruf setSelectionin einer separaten View.post(Runnable)ausführbaren Datei erhalten hat, die von ausgelöst wurde (Repost von diesem Thema).

Also, für mich funktioniert dieser Code:

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

Edit 16.05.2019: Im Moment verwende ich dafür die Kotlin-Erweiterung:

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

und dann - editText.placeCursorToEnd ().

Anton Derevyanko
quelle
Danke, das hat wirklich bei mir funktioniert. Ich habe versucht, setSelection aufzurufen, aber es funktioniert nicht. In meinem Fall habe ich versucht, ein festes Präfix zum Bearbeiten von Text festzulegen. Nachdem ich das Präfix festgelegt hatte, musste ich den Cursor auf das Ende des Präfix setzen, damit der Benutzer Daten nach dem Präfix eingeben kann. Da ich setSelection im Konstruktor eines TextWatcher ausgeführt habe, hat dies möglicherweise deshalb nicht funktioniert. Aber Ihre Lösung hat großartig funktioniert!
Zauberstabmacher
Ich verwende diese Post-Methode in der Clickablespan-Methode meines MultiAutoCompleteTextView und sie funktioniert ..... Ich möchte, dass sich der Cursor am Ende bewegt, sobald auf das Löschsymbol in der Textspanne geklickt wird ... Sie funktioniert in allen aktuellen Android-Handys. ..aber in alten Versionen dauert es einige Zeit nach dem ersten Klick ... alle meine anderen Elemente werden nicht anklickbar ... irgendein Hinweis?
VijayRaj
1
Ich weiß nicht warum, aber dies ist die einzige, die für mich funktioniert! Mein Bearbeitungstext hat einen Listener für Fokus / Textänderung und wird in ein TextInputLayout eingeschlossen. Eines dieser Dinge ist es, es durcheinander zu bringen.
Daniel Wilson
42

Sie können den Cursor auch wie folgt am Ende des Textes in der EditTextAnsicht platzieren:

EditText et = (EditText)findViewById(R.id.textview);
int textLength = et.getText().length();
et.setSelection(textLength, textLength);
toobsco42
quelle
27
editText.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        editText.setSelection(editText.getText().length());
        return false;
    }
});
Mario
quelle
21

Dies ist eine weitere mögliche Lösung:

et.append("");

Probieren Sie diese Lösung einfach aus, wenn sie aus irgendeinem Grund nicht funktioniert:

et.setSelection(et.getText().length());
Kreshnik
quelle
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);

Es funktioniert gut für mich!

Anh Duy
quelle
12

In meinem Fall habe ich das folgende Kotlin ext erstellt. Funktion, kann für jemanden nützlich sein

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

Dann wie folgt verwenden

mEditText.focus()
Igor Siqueira
quelle
12

Wenn Ihr EditText nicht klar ist:

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

oder

editText.setText(null);
editText.append("New text");
Leo Droidcoder
quelle
12

Sie sollten dies mit Hilfe der EditText'sMethode erreichen können setSelection(), siehe hier

Maximus
quelle
10

Ich denke, das kann erreichen, was Sie wollen.

 Editable etext = mSubjectTextEditor.getText();
 Selection.setSelection(etext, etext.length());
Li Che
quelle
Wenn meine Beobachtungen korrekt sind, wird für jedes Widget eine Instanz von android.widget.TextView $ IClipboardDataPasteEventImpl erzeugt. Am Ende hatte ich Tonnen von ihnen. Anscheinend werden sie irgendwann aufgeräumt, scheinen aber den Speicherverbrauch zu erhöhen. Ich hatte 12 Instanzen eines Dialogs, es ist nur der Dominator (was ihn am Leben hält), der oben erwähnte Instanz.
AgentKnopf
Platzieren Sie diesen Code an einer geeigneten Stelle im Code (wo Sie Text direkt an EText anhängen). Vielen Dank!
Sud007
9

Die Frage ist alt und beantwortet, aber ich denke, es kann nützlich sein, diese Antwort zu haben, wenn Sie die neu veröffentlichten DataBinding-Tools für Android verwenden möchten. Legen Sie dies einfach in Ihrem XML fest:

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

Geben Sie hier die Bildbeschreibung ein

Hallo, versuche das

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

Rahul Patil
quelle
5

Wenn Sie den gesamten Text auswählen und nur neuen Text anstelle des alten eingeben möchten, können Sie verwenden

    android:selectAllOnFocus="true"
ar-g
quelle
5

Das funktioniert

Editable etext = edittext.getText();
Selection.setSelection(etext,edittext.getText().toString().length());
Hardik Vasani
quelle
5

editText.setSelectionist die Magie hier. Grundsätzlich können Sie mit der Auswahl den Cursor an einer beliebigen Position platzieren.

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

Dadurch wird der Cursor an das Ende von EditText gesetzt. Grundsätzlich editText.getText().length()gibt Ihnen Textlänge. Dann benutzt du setSelectionmit Länge.

editText.setSelection(0);

Hiermit wird der Cursor auf die Startposition (0) gesetzt.

Khemraj
quelle
4

Alle anderen Codes, die ich getestet habe, funktionierten nicht gut, da der Benutzer das Caret / den Cursor immer noch in der Mitte der Zeichenfolge platzieren konnte (Beispiel: 12 | 3.00 - wobei | der Cursor ist). Meine Lösung setzt den Cursor immer am Ende der Zeichenfolge, wenn der EditText berührt wird.

Die ultimative Lösung ist:

// 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) {

            }
        });

Ich hoffe es hilft!

Daniel Almeida
quelle
3

Für ViewModel, LiveData und Datenbindung

Ich brauchte diese Funktionalität für die EditTextmehrzeilige Unterstützung in meiner Notizen-App. Ich wollte den Cursor am Ende des Textes, wenn der Benutzer zu dem Fragment navigiert, das Notiztext enthält.

Die vom Djleop vorgeschlagene Lösung kommt nahe. Das Problem dabei ist jedoch, dass, wenn der Benutzer den Cursor zum Bearbeiten irgendwo in die Mitte des Textes setzt und mit der Eingabe beginnt, der Cursor wieder zum Ende des Texts springt. Dies geschah, weil dieLiveData neue Wert ausgegeben wurde und der Cursor erneut zum Ende des Textes sprang, was dazu führte, dass der Benutzer den Text nicht irgendwo in der Mitte bearbeiten konnte.

Um dies zu lösen, benutze ich MediatorLiveDatadie Länge und weise sie Stringnur einmal mit einem Flag zu. Dadurch lesen die LiveData den Wert nur einmal, dh wenn der Benutzer zum Fragment navigiert. Danach kann der Benutzer den Cursor an einer beliebigen Stelle platzieren, an der er den Text dort bearbeiten möchte.

ViewModel

private var accessedPosition: Boolean = false

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

Hier yourObjectist eine weitere LiveData, die aus der Datenbank abgerufen wurde und den String-Text enthält, den Sie in der Datenbank anzeigenEditText .

Binden Sie dies MediatorLiveDatadann mit dem Bindungsadapter an Ihren EditText.

XML

Verwendet die bidirektionale Datenbindung zum Anzeigen von Text sowie zum Akzeptieren der Texteingabe.

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

Bindungsadapter

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

Event Klasse

Die EventKlasse hier ist wie ein SingleLiveEvent, das von Jose Alcérreca von Google geschrieben wurde. Ich benutze es hier, um mich um die Bildschirmrotation zu kümmern. Durch die Verwendung der Single Eventwird sichergestellt, dass der Cursor nicht zum Ende des Texts springt, wenn der Benutzer den Text irgendwo in der Mitte bearbeitet und sich der Bildschirm dreht. Es behält die gleiche Position bei, wenn sich der Bildschirm dreht.

Hier ist die EventKlasse:

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
}

Dies ist die Lösung, die für mich funktioniert und eine gute Benutzererfahrung bietet. Hoffe, es hilft auch in Ihren Projekten.

Yogesh Umesh Vaity
quelle
Diese Antwort muss weit oben sein. Vielen Dank
Abdul Rahman Shamair
2

ähnlich wie @Anh Duys Antwort, aber es hat bei mir nicht funktioniert. Ich brauchte auch den Cursor, um nur dann zum Ende zu gelangen, wenn der Benutzer auf den Bearbeitungstext tippt und danach noch die Position des Cursors auswählen kann. Dies ist der einzige Code, der für mich funktioniert hat

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;
    }
});
Fonix
quelle
2

Dies macht den Trick sicher :

    editText.setText("");
    if (!TextUtils.isEmpty(text)) {
        editText.append(text);
    }
Alécio Carvalho
quelle
2
etSSID.setSelection(etSSID.getText().length());
Geschwister Varghese
quelle
2

Die obigen Antworten haben bei mir nicht funktioniert. Also habe ich eine neue Lösung gefunden. Das ist vielleicht hilfreich für jemanden. Ich habe die neueste Version von Android Studio verwendet, dh 3.5 zum aktuellen Datum. Vielleicht war dies der Grund, warum die obigen Antworten keine Wirkung zeigten.

CODE:

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

Hier ist das erste Argument der Spannable-Textwert, mit dem Sie spielen möchten, während das zweite Argument der Indexwert ist. Da der Cursor am Ende des Textes stehen soll, haben wir getText (). Length () verwendet, das die Länge des Textes zurückgibt

Prajwal W.
quelle
1
Gern geschehen! Viel Spaß beim Codieren!
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) {

    }
}

Verwenden Sie diesen CustomEditText in Ihrer XML-Datei. Dies funktioniert. Ich habe das getestet und es funktioniert für mich.

kishna.147
quelle
1

Wenn Sie den Cursor in der EditText-Ansicht am Ende des Texts platzieren möchten

 EditText rename;
 String title = "title_goes_here";
 int counts = (int) title.length();
 rename.setSelection(counts);
 rename.setText(title);
Mujahid Khan
quelle