Umieść kursor na końcu tekstu w EditText


883

Zmieniam wartość EditTextwłączenia keyListener.

Ale kiedy zmieniam tekst, kursor przesuwa się na początek EditText. Potrzebuję kursora na końcu tekstu.

Jak przesunąć kursor na koniec tekstu w EditText.


3
Natknąłem się na ten sam problem. Ale lepiej zadałem sobie pytanie, dlaczego tak się dzieje, abym mógł wcześniej rozwiązać problem, zamiast samemu przenosić karetkę.
kaneda

3
@kaneda Całkowicie się zgadzam, jednak byłoby pomocne, gdybyś dodał rzeczywiste rozwiązanie.
AgentKnopf

1
@Zainodis To była tylko myśl. Tak jak powiedziałem, natknąłem się na ten sam problem, co niekoniecznie oznacza, że ​​znalazłem rozwiązanie. W moim przypadku miałem problem ze EditTexts jako elementy ListView. Jeśli chodzi o eksperymenty, dokonałem pewnych zmian w samym ListViewkodzie źródłowym, który jest dość złożoną bestią, i przetestowałem na emulatorze. Było to związane z zarządzaniem kontrolą fokusu przez komponent. Oczywiście nie jest to rozwiązanie, które mógłbym pomóc naszemu przyjacielowi. :)
kaneda


To nie działa w ramach OnFocusChangedwywołania zwrotnego. Rozwiązaniem jest umieszczenie setSelection w pliku wykonywalnym i uruchomienie go w głównym wątku. Sprawdź tutaj stackoverflow.com/a/32156989/4514796
Ali Nem

Odpowiedzi:


1318

Spróbuj tego:

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

15
To nie działa w moim przypadku. Metoda setSelection () wydaje się nie mieć żadnego efektu. Mój widok EditText zawiera ImageSpans. Czy istnieje jakieś inne obejście?
toobsco42

@marqss, miałem ten sam problem i działałem idealnie dla mnie. Korzystałem z EditText w oknie dialogowym i wstępnie wypełniałem tekst z ekranu głównego. Kiedy tak się dzieje, kursor pozostawał na początku, a nie na końcu, ale po wypróbowaniu Twojej sugestii wszystko było w porządku, tak jak chciałem. Dziękujemy za opublikowanie tego.
Vincy,

4
Hej @Mullay, teraz radzę sobie z tym, zastępując onSelectionChanged()metodę EditTextklasy: 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
Być może będziesz musiał użyć et.post (nowy Runnable ({... et.setSel ...), aby dostać się do kolejki. Dzieje się tak, ponieważ Android czeka na pewne elementy układu, aż do lepszego czasu, publikując, więc jeśli spróbujesz ustawić opcję Select zanim system się zakończy, cofnie twoją pracę
MinceMan,

1
Działa tutaj, dzięki za odpowiedź. Ale powinieneś zrobić tak: editText.setText (s); editText.setSelection (editText.getText (). length ()); // po
setText

223

Istnieje funkcja o nazwie append dla ediitext, która dołącza wartość ciągu do bieżącej wartości edittext i umieszcza kursor na końcu wartości. Możesz mieć wartość ciągu jako bieżącą samą wartość ediitext i wywołać append ();

myedittext.append("current_this_edittext_string"); 

1
Jeśli masz już tekst w EditText, po prostu napiszmyedittext.append("");
ymerdrengene

4
Aplikacja @ymerdrengene po prostu myedittext.append("");nie działała dla mnie!
Chintan Shah,

4
Jest to idealne, ponieważ po prostu zastępuje wiersz kodu, który miałem. Używałem edittextfield.setText i po prostu zamieniłem go na append. Bardzo prosta.
theblitz

Zależy od użycia, jeśli to działa, czy nie. Dla mnie tak nie było. Używanie Selectionjest poprawnym sposobem na osiągnięcie tego IMO.
sud007

139

Kotlin :

ustaw kursor w pozycji początkowej :

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

ustaw kursor na końcu EditText :

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

Pod kodem należy umieścić kursor po drugim znaku:

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

JAVA :

ustaw kursor w pozycji początkowej :

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

ustaw kursor na końcu EditText :

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

Pod kodem należy umieścić kursor po drugim znaku:

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

1
Mogą zastąpić findViewById(R.id.edittext_id) as EditTextz findViewById<EditText>(R.id.edittext_id)lub po prostu uniknąć casting w przypadku korzystaniaAPI 26+
Evin1_

96

Jeśli zadzwoniłeś setTextwcześniej, a nowy tekst nie dostał się w fazie układu, zadzwoń setSelectionw osobnym uruchamianym przez View.post(Runnable)(repost z tego tematu).

Dla mnie ten kod działa:

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

Edytuj 16.05.2019: Teraz używam do tego rozszerzenia Kotlin:

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

a następnie - editText.placeCursorToEnd ().


Dzięki, to naprawdę dla mnie działało. Próbowałem wywołać setSelection, ale to nie zadziała. W moim przypadku próbowałem ustawić stały prefiks do edycji tekstu, więc po ustawieniu prefiksu musiałem ustawić kursor na końcu prefiksu, aby użytkownik mógł wprowadzić dane po prefiksie. Ponieważ robiłem setSelection w konstruktorze TextWatchera, być może dlatego nie działało. Ale twoje rozwiązanie działało świetnie!
Wand Maker

Używam tej metody postu w metodzie Clickablespan w MultiAutoCompleteTextView i działa ... Chcę, aby kursor przesuwał się na końcu po kliknięciu ikony usuwania w zakresie tekstu ... Działa we wszystkich najnowszych telefonach z Androidem. ... ale w starych wersjach zajmuje to trochę czasu po pierwszym kliknięciu ... wszystkie moje inne elementy nie są klikalne ... jakaś wskazówka?
VijayRaj,

1
Nie wiem dlaczego, ale to jedyna, która działa dla mnie! Mój tekst edycji ma detektor fokusa / tekstu zmieniony i jest zawinięty w TextInputLayout. Jedną z tych rzeczy jest zepsucie.
Daniel Wilson,

42

Możesz również umieścić kursor na końcu tekstu w EditTextwidoku w następujący sposób:

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

To kolejne możliwe rozwiązanie:

et.append("");

Wypróbuj to rozwiązanie, jeśli z jakiegoś powodu nie działa:

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);

To działa dobrze dla mnie!


12

W moim przypadku stworzyłem następujący ext kotlin. funkcja, może być przydatna dla kogoś

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

Następnie użyj w następujący sposób

mEditText.focus()

12

Jeśli Twój EditText nie jest jasny:

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

lub

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

12

Powinieneś być w stanie to osiągnąć za pomocą EditText'smetody setSelection(), patrz tutaj


10

myślę, że to może osiągnąć to, czego chcesz.

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

Jeśli moje obserwacje są poprawne, powoduje to wystąpienie instancji android.widget.TextView $ IClipboardDataPasteEventImpl dla każdego widżetu. Skończyło mi się ich mnóstwo. Najwyraźniej zostaną ostatecznie oczyszczone, ale wydają się zwiększać zużycie pamięci. Miałem 12 wystąpień jednego dialogu, jest to jedyny dominujący (co utrzymuje go przy życiu) będący wyżej wspomnianym wystąpieniem.
AgentKnopf

Umieszczenie tego fragmentu kodu w odpowiednim miejscu w kodzie (tam, gdzie dodajesz tekst bezpośrednio do EText). Dzięki!
sud007

9

Pytanie jest stare i udzielono odpowiedzi, ale myślę, że przydatne może być otrzymanie tej odpowiedzi, jeśli chcesz korzystać z nowo wydanych narzędzi DataBinding dla systemu Android, po prostu ustaw to w pliku XML:

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

6

wprowadź opis zdjęcia tutaj

Witaj, spróbuj tego

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


5

Jeśli chcesz zaznaczyć cały tekst i po prostu wpisać nowy tekst zamiast starego, możesz użyć

    android:selectAllOnFocus="true"

5

To działa

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

5

editText.setSelectionjest magia tutaj. Zasadniczo zaznaczenie umożliwia umieszczenie kursora w dowolnej pozycji.

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

To umieszcza kursor na końcu EditText. Zasadniczo editText.getText().length()daje długość tekstu. Następnie używasz setSelectionz długością.

editText.setSelection(0);

Służy do ustawiania kursora w pozycji początkowej (0).


4

Wszystkie inne kody, które testowałem, nie działały dobrze, ponieważ użytkownik mógł nadal umieszczać kursor / kursor w dowolnym miejscu w środku łańcucha (np .: 12 | 3,00 - gdzie | jest kursorem). Moje rozwiązanie zawsze umieszcza kursor na końcu łańcucha, gdy tylko dotknie się go w EditText.

Ostatecznym rozwiązaniem jest:

// 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"/>

@ ciąg / kwota = „0,00” @ ciąg / wartość_ zero = „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) {

            }
        });

Mam nadzieję, że to pomoże!


3

W przypadku ViewModel, LiveData i powiązania danych

Potrzebowałem tej funkcji EditTextz obsługą wielu linii w mojej aplikacji do notatek. Chciałem kursor na końcu tekstu, gdy użytkownik przechodzi do fragmentu zawierającego tekst notatki.

Rozwiązanie sugerowane przez djleopa jest bliskie. Problem polega jednak na tym, że jeśli użytkownik umieści kursor gdzieś pośrodku tekstu do edycji i zacznie pisać, kursor przeskoczy ponownie na koniec tekstu. Stało się tak, ponieważ LiveDatawyemitowałyby nową wartość, a kursor ponownie przeskoczyłby na koniec tekstu, powodując, że użytkownik nie byłby w stanie edytować tekstu gdzieś pośrodku.

Aby rozwiązać ten problem, używam MediatorLiveDatai przypisuję mu długość Stringtylko raz za pomocą flagi. Spowoduje to, że LiveData odczyta wartość tylko raz, to znaczy, gdy użytkownik przejdzie do fragmentu. Następnie użytkownik może umieścić kursor w dowolnym miejscu, w którym chce edytować tekst.

ViewModel

private var accessedPosition: Boolean = false

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

Oto yourObjectkolejna funkcja LiveData pobrana z bazy danych zawierającej tekst String, który wyświetlasz w EditText.

Następnie powiąż to MediatorLiveDataz tekstem edycji za pomocą adaptera wiązania.

XML

Używa dwukierunkowego powiązania danych do wyświetlania tekstu oraz akceptowania wprowadzania tekstu.

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

Adapter do wiązania

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

Event klasa

Ta Eventklasa jest jak SingleLiveEvent napisany przez Jose Alcérreca z Google. Używam go tutaj, aby zadbać o rotację ekranu. Użycie singla Eventsprawi, że kursor nie przeskoczy na koniec tekstu, gdy użytkownik edytuje tekst gdzieś pośrodku, a ekran się obraca. Utrzymuje tę samą pozycję, gdy ekran się obraca.

Oto Eventklasa:

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
}

To rozwiązanie działa dla mnie i zapewnia dobre wrażenia użytkownika. Mam nadzieję, że pomoże to również w twoich projektach.


Ta odpowiedź musi być znacznie wyższa. Wielkie dzięki
Abdul Rahman Shamair

2

podobna do odpowiedzi @Anh Duy, ale dla mnie to nie zadziałało. Potrzebowałem również kursora, aby przejść do końca tylko wtedy, gdy użytkownik stuknie edytowany tekst i nadal będę mógł wybrać pozycję kursora później, jest to jedyny kod, który działał dla mnie

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

Robi to bezpiecznie :

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


2

Powyższe odpowiedzi nie działały dla mnie. Więc znalazłem nowe rozwiązanie. To może komuś pomóc. Korzystam z najnowszej wersji Androida Studio, tj. 3.5 na dzień dzisiejszy. Może to może być powód, dla którego powyższe odpowiedzi nie wykazały żadnego efektu.

KOD:

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

Tutaj pierwszy argument jest wartością tekstową Spannable, którą chcesz grać, podczas gdy drugi argument jest wartością indeksu. Ponieważ chcemy, aby kursor znajdował się na końcu tekstu, wzięliśmy getText (). Length (), która zwraca długość tekstu


1
Cała przyjemność po mojej stronie! Happy Coding!
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) {

    }
}

Użyj tego pliku CustomEditText w pliku XML, to zadziała. Przetestowałem to i działa dla mnie.


1

Jeśli chcesz umieścić kursor na końcu tekstu w widoku EditText

 EditText rename;
 String title = "title_goes_here";
 int counts = (int) title.length();
 rename.setSelection(counts);
 rename.setText(title);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.