Помістіть курсор в кінці тексту в EditText


883

Я змінюю значення EditTextна keyListener.

Але коли я змінюю текст, курсор переміщується до початку EditText. Мені потрібен курсор у кінці тексту.

Як перемістити курсор до кінця тексту в a EditText.


3
Я зіткнувся з тим же питанням. Але те, що я краще запитав себе, це чому це відбувається, щоб я міг вирішити проблему раніше, ніж замість того, щоб самостійно переносити каре.
kaneda

3
@kaneda Я повністю згоден, однак було б корисно, якби ви додали власне рішення.
AgentKnopf

1
@Zainodis Це була лише думка. Як я вже говорив, я натрапив на те саме питання, що не обов'язково означає, що я знайшов рішення. У моєму випадку у мене виникла проблема з EditTexts як предметами а ListView. Що стосується експериментів, я вніс деякі зміни у сам ListViewвихідний код, який є досить складним звіром, і випробував на емуляторі. Це було пов'язано з керуванням управлінням фокусом, зробленим компонентом. Тож звичайно це не рішення, яке я міг би дати, щоб допомогти нашому другу. :)
kaneda

2
можливий дублікат Android edittext - випуск курсору
settextmethod

Це не працює всередині OnFocusChangedзворотного дзвінка. Рішення в тому, щоб помістити setSelection всередину прогону і запустити його на основну нитку. Перевірте тут stackoverflow.com/a/32156989/4514796
Алі Нем

Відповіді:


1318

Спробуйте це:

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

15
У моєму випадку це не працює. Метод setSelection (), здається, не має ефекту. Мій перегляд EditText містить ImageSpans. Чи є якийсь інший спосіб вирішення?
toobsco42

@marqss, у мене був той самий випуск і працював ідеально для мене. Я використовував EditText для діалогового вікна та попередньо заповнення тексту з головного екрану. Коли це трапляється, курсор залишався на початку, а не в кінці, але після того, як я спробував вашу пропозицію, все просто добре, як я хотів. Дякуємо, що опублікували це.
Вінсі

4
Привіт @Mullay, я зараз обробляю це, onSelectionChanged()EditTextpublic 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); }
переосмислюючи

19
Можливо, вам доведеться використовувати et.post (новий Runnable ({... et.setSel ...), щоб потрапити в чергу. Це тому, що android очікує зробити деякі елементи макета до кращого часу, розмістивши повідомлення, тому якщо ви спробуєте встановитиSelection до завершення роботи системи вона скасує вашу роботу
MinceMan

1
Тут працює, дякую за вашу відповідь. Але вам слід зробити так: editText.setText (s); editText.setSelection (editText.getText (). length ()); // після setText
smileVann

223

Існує функція під назвою append for ediitext, яка додає значення рядка до поточного значення редакційного тексту і розміщує курсор в кінці значення. Ви можете мати значення рядка як поточне значення ediitext сам по собі та викликати append ();

myedittext.append("current_this_edittext_string"); 

1
Якщо у вас вже є текст у вашому EditText, просто напишітьmyedittext.append("");
ymerdrengene

4
@ymerdrengene тільки подання заявки myedittext.append("");не працювало для мене!
Чінтан Шах

4
Це ідеально, оскільки він просто замінює рядок коду, який у мене був. Використовував edittextfield.setText і просто поміняв його на додавання. Дуже просто.
theblitz

Залежить від використання, чи працює це чи ні. Для мене це не сталося. Використання Selectionє правильним способом досягнення цього ІМО.
sud007

139

Котлін :

встановити курсор у вихідне положення :

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

встановіть курсор на кінець EditText :

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

Нижче коду слід розмістити курсор після другого символу:

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

JAVA :

встановити курсор у вихідне положення :

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

встановіть курсор на кінець EditText :

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

Нижче коду слід розмістити курсор після другого символу:

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

1
Може замінити findViewById(R.id.edittext_id) as EditTextз findViewById<EditText>(R.id.edittext_id)або просто уникнути виливок при використанніAPI 26+
Evin1_

96

Якщо ви зателефонували setTextраніше, і новий текст не отримав фазовий виклик макета setSelectionв окремому запущеному режимі View.post(Runnable)(репост з цієї теми).

Отже, для мене цей код працює:

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

Редагувати 16.05.2019: Зараз для цього я використовую розширення Kotlin:

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

а потім - editText.placeCursorToEnd ().


Дякую, це справді працювало для мене. Я намагався зателефонувати на setSelection, але це не вийде. У моєму випадку я намагався встановити фіксований префікс для редагування тексту, і тому після встановлення префіксу мені потрібно було встановити курсор на кінець префікса, щоб користувач міг вводити дані після префікса. Оскільки я робив setSelection в конструкторі TextWatcher, можливо, це не спрацювало. Але ваше рішення спрацювало чудово!
Maker Wand Maker

Я використовую цей метод публікації у моєму методі Clickablespan MultiAutoCompleteTextView, і він працює ..... Я хочу, щоб курсор перемістився наприкінці, після того, як натиснеться значок видалення в текстовому проміжку ... Він працює у всіх останніх мобільних телефонах Android. ..але у старих версіях проходить деякий час після першого клацання ... всі мої інші елементи не стають натисканнями ... будь-які підказки ??
VijayRaj

1
Я не знаю чому, але це єдине, що працює для мене! У моєму редагувальному тексті прослуховується фокус / текст, змінений слухачем, і загорнуто у TextInputLayout. Одна з таких речей - це зіпсувати це.
Даніель Вілсон

42

Ви також можете розмістити курсор у кінці тексту у EditTextподаному вигляді:

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

Це ще одне можливе рішення:

et.append("");

Просто спробуйте це рішення, якщо воно не працює з будь-якої причини:

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

Це добре працює для мене!


12

У моєму випадку я створив наступний kotlin ext. функція, може бути корисною для когось

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

Потім використовуйте наступним чином

mEditText.focus()


12

Ви повинні мати можливість досягти цього за допомогою EditText'sметоду setSelection(), дивіться тут


10

Я думаю, що цим можна досягти того, чого ти хочеш.

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

Якщо мої спостереження правильні, це породжує примірник android.widget.TextView $ IClipboardDataPasteEventImpl для кожного віджета. Я закінчив з ними тонни. Мабуть, вони з часом очищаються, але, здається, збільшують споживання пам'яті. У мене було 12 примірників одного діалогу, вищезгаданим екземпляром є лише домінатор (що підтримує його живим).
AgentKnopf

Розміщення цього фрагмента коду у відповідному положенні в коді (де ви додаєте текст безпосередньо до EText). Дякую!
sud007

9

Питання давнє і відповіли, але я думаю, що це може бути корисно мати цю відповідь, якщо ви хочете використовувати нещодавно випущені засоби DataBinding для Android, просто встановіть це у своєму XML:

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

6

введіть тут опис зображення

Привіт, спробуйте це

 <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 pointКурсор


5

Якщо ви хочете вибрати весь текст і просто ввести новий текст замість старого, ви можете використовувати

    android:selectAllOnFocus="true"


5

editText.setSelectionтут магія. В основному вибір дає вам курсор місця в будь-якій потрібній вам позиції.

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

Це додає курсор до кінця EditText. В основному editText.getText().length()дає вам довжину тексту. Потім ви використовуєте setSelectionз довжиною.

editText.setSelection(0);

Він призначений для встановлення курсору у вихідне положення (0).


4

Усі інші тестовані коди не спрацювали добре через те, що користувач все ще може розміщувати карету / курсор кудись посередині рядка (напр .: 12 | 3.00 - де | знаходиться курсор). Моє рішення завжди кладе курсор у кінець рядка всякий раз, коли дотик виникає на EditText.

Кінцевим рішенням є:

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

            }
        });

Сподіваюся, це допомагає!


3

Для перегляду ViewModel, LiveData та даних

Мені потрібна ця функціональність для EditTextбагатолінійної підтримки в моєму додатку. Мені хотілося, щоб курсор в кінці тексту, коли користувач перейшов до фрагмента, який містить текст примітки.

Рішення, запропоноване djleop, наближається. Але проблема з цим полягає в тому, що якщо користувач кладе курсор десь посередині тексту для редагування і почне вводити текст, курсор знову перескочить до кінця тексту. Це сталося тому, щоLiveData виправити нове значення, а курсор знову перескочить на кінець тексту, в результаті чого користувач не зможе редагувати текст десь посередині.

Для вирішення цього питання я використовую MediatorLiveDataі призначаю його довжину Stringлише один раз, використовуючи прапор. Це призведе до того, що LiveData прочитає значення лише один раз, тобто коли користувач перейде до фрагмента. Після цього користувач може розмістити курсор у будь-якому місці, де він хоче редагувати текст.

ViewModel

private var accessedPosition: Boolean = false

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

Ось yourObjectще один LiveData, отриманий з бази даних, що містить текст String, який ви відображаєте вEditText .

Потім MediatorLiveDataприв’яжіть це до свого EditText за допомогою адаптера прив'язки.

XML

Використовує двостороння прив'язка даних для відображення тексту, а також для прийняття тексту.

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

Перев'язувальний адаптер

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

Event клас

EventКлас тут як SingleLiveEvent написаний Хосе Alcérreca від Google. Я використовую його тут, щоб подбати про обертання екрана. Використовуючи сингл Event, переконайтеся, що курсор не перескочить до кінця тексту, коли користувач редагує текст десь посередині і екран повернеться. Він буде зберігати те саме положення, коли екран обертається.

Ось Eventклас:

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
}

Це рішення, яке працює для мене і забезпечує хороший досвід користувача. Сподіваємось, це допоможе і у ваших проектах.


Цю відповідь потрібно домогтися. Велике спасибі
Абдул Рахман Шамайр

2

подібно до відповіді @Anh Duy, але це не спрацювало для мене. мені також потрібен був курсор для переміщення до кінця лише тоді, коли користувач натискає текст редагування і все-таки зможе потім вибрати позицію курсору, це єдиний код, який працював для мене

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

Наведені вище відповіді не працювали на мене. Тож я знайшов нове рішення. Це може бути корисно для когось. Я використовував останню версію Android Studio, тобто 3,5 на сьогоднішній день. Можливо, це може бути причиною, чому вищезгадані відповіді не показали жодного ефекту.

КОД:

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

Тут перший аргумент - це текстове значення Spannable, яке потрібно відтворити, тоді як другий аргумент - це значення індексу. Оскільки ми хочемо курсор в кінці тексту, ми взяли getText (). Length (), який повертає довжину тексту


1
Моє задоволення! Щасливе кодування!
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) {

    }
}

Користуйтеся цим CustomEditText у вашому XML-файлі, це працюватиме. Я перевірив це, і це працює на мене.


1

Якщо ви хочете розмістити курсор у кінці тексту у вікні EditText

 EditText rename;
 String title = "title_goes_here";
 int counts = (int) title.length();
 rename.setSelection(counts);
 rename.setText(title);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.