Поместите курсор в конец текста в EditText

972

Я меняю значение EditTextвключения keyListener.

Но когда я меняю текст, курсор перемещается в начало EditText. Мне нужно, чтобы курсор был в конце текста.

Как переместить курсор в конец текста в файле EditText.

5
  • 3
    Я столкнулся с той же проблемой. Но я лучше спросил себя, почему это происходит, чтобы я мог решить проблему раньше, вместо того, чтобы самому перемещать курсор.
    kaneda
    11 дек '12 в 18:55
  • 4
    @kaneda Я полностью согласен, однако было бы полезно, если бы вы добавили реальное решение. 03 янв.
  • 1
    @Zainodis Это была просто мысль. Как я уже сказал, я столкнулся с той же проблемой, что не обязательно означает, что я нашел решение. В моем случае у меня была проблема с EditTexts как элементами файла ListView. Что касается экспериментов, я внес некоторые изменения в сам ListViewисходный код, который представляет собой довольно сложный зверь, и протестировал на эмуляторе. Это было связано с управлением контролем фокуса, осуществляемым компонентом. Так что, конечно, это не решение, которое я мог бы предложить, чтобы помочь нашему другу. :)
    kaneda
    03 янв.
  • 2
    возможный дубликат Android edittext - проблема с курсором settextmethod
    AZ_
    23 апр.
  • Это не работает внутри OnFocusChangedобратного вызова. Решение состоит в том, чтобы поместить setSelection в исполняемый файл и запустить его в основном потоке. Проверьте здесь stackoverflow.com/a/32156989/4514796
    Ali Nem
    6 мая '20 в 10:34
1412

Попробуй это:

ОБНОВИТЬ:

Котлин:

editText.setSelection(editText.length())//placing cursor at the end of the text

Джава:

editText.setSelection(editText.getText().length());
7
  • 16
    В моем случае это не работает. Кажется, что метод setSelection () не действует. Мое представление EditText содержит ImageSpans. Есть ли другой способ обхода проблемы? 03 янв.
  • @marqss, у меня была такая же проблема, и я отлично работал. Я использовал EditText в диалоге и предварительно заполнял текст с главного экрана. Когда это происходит, курсор остается в начале, а не в конце, но после того, как я попробовал ваше предложение, все в порядке, как я хотел. Спасибо за публикацию.
    Vincy
    25 янв.
  • 5
    Привет, @Mullay, теперь я справляюсь с этим, переопределяя onSelectionChanged()метод EditTextкласса: 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); } 28 фев '13 в 17:45
  • 22
    Возможно, вам придется использовать et.post (new Runnable ({... et.setSel ...), чтобы попасть в очередь. Это связано с тем, что Android ожидает выполнения некоторых макетов до подходящего времени, отправляя сообщение, поэтому, если вы попытаетесь setSelection прежде чем система будет завершена, она отменит вашу работу. 07 дек.
  • 1
    Здесь он работает, спасибо за ответ, но вы должны сделать это так: editText.setText (s); editText.setSelection (editText.getText (). length ()); // после setText 30 марта '14 в 18: 102014-03-30 15:10
239

Существует функция под названием append для ediitext, которая добавляет строковое значение к текущему значению edittext и помещает курсор в конец значения. Вы можете использовать строковое значение как текущее значение ediitext и вызвать append ();

myedittext.append("current_this_edittext_string"); 
4
  • 1
    Если у вас уже есть текст в вашем EditText, просто напишите myedittext.append(""); 24 апр '15 в 13:48
  • 4
    @ymerdrengene просто подать заявку myedittext.append("");мне не удалось! 11 дек.
  • 4
    Это идеально, потому что просто заменяет строку кода, которая у меня была. Использовал edittextfield.setText и просто заменил его на добавление. Очень простой. 22 фев '16 в 14:55
  • Зависит от использования, работает это или нет. Для меня это не так. Использование Selection- это правильный способ достижения этого ИМО.
    sud007
    03 июл.
154

Котлин :

установите курсор в начальную позицию :

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)

ЯВА :

установите курсор в начальную позицию :

 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
  • 1
    Может заменить findViewById(R.id.edittext_id) as EditTextс findViewById<EditText>(R.id.edittext_id)или просто избежать отливку при использованииAPI 26+
    Evin1_
    25 июн.
130

Если вы звонили setTextраньше, и новый текст не получил вызова фазы макета setSelectionв отдельном runnable, запущенном 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 ().

3
  • Спасибо, это действительно сработало для меня. Я пытался вызвать setSelection, но это не сработало. В моем случае я пытался установить фиксированный префикс для редактирования текста, поэтому после установки префикса мне нужно было установить курсор в конец префикса, чтобы пользователь мог вводить данные после префикса. Поскольку я делал setSelection в конструкторе TextWatcher, возможно, поэтому это не сработало. Но ваше решение отлично сработало! 02 сен '13 в 8:33
  • Я использую этот метод публикации в моем методе Clickablespan MultiAutoCompleteTextView, и он работает ... Я хочу, чтобы курсор перемещался в конце после нажатия значка удаления в текстовом диапазоне ... Он работает на всех последних мобильных устройствах Android. ..но в старых версиях это занимает некоторое время после первого щелчка ... все мои другие элементы не становятся кликабельными ... любая подсказка ?? 10 сен.
  • 1
    Не знаю почему, но это единственное, что мне подходит! Мой текст редактирования имеет прослушиватель измененного фокуса / текста и заключен в TextInputLayout. Одна из этих вещей - все испортить. 20 мая '16 в 18:59
43 год

Вы также можете поместить курсор в конец текста в EditTextпредставлении следующим образом:

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

Это еще одно возможное решение:

et.append("");

Просто попробуйте это решение, если оно не работает по какой-либо причине:

et.setSelection(et.getText().length());
16

В моем случае я создал следующий kotlin ext. функция, может быть кому-то полезна

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

Затем используйте следующее

mEditText.focus()
1
  • tnx. Фокус на запросе был отличным.
    Reza
    9 дек '20 в 12:11
14

Если ваш EditText непонятен:

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

или

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

Вы должны добиться этого с помощью EditText'sметода setSelection(), см. Здесь

13
/**
 * 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

Я думаю, это может достичь того, чего вы хотите.

 Editable etext = mSubjectTextEditor.getText();
 Selection.setSelection(etext, etext.length());
2
  • Если мои наблюдения верны, это порождает экземпляр android.widget.TextView $ IClipboardDataPasteEventImpl для каждого виджета. У меня их было много. По-видимому, они в конечном итоге очищаются, но, похоже, увеличивают потребление памяти. У меня было 12 экземпляров одного диалога, это только доминатор (который поддерживает его), являющийся вышеупомянутым экземпляром. 02 янв.
  • Поместите этот фрагмент кода в соответствующую позицию в коде (где вы добавляете текст непосредственно в EText). Спасибо!
    sud007
    03 июл.
10

Вопрос старый, и на него есть ответ, но я думаю, что может быть полезно получить этот ответ, если вы хотите использовать недавно выпущенные инструменты DataBinding для Android, просто установите это в своем XML:

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

editText.setSelectionздесь волшебство. В основном выбор дает вам возможность разместить курсор в любом месте, которое вы хотите.

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

Это помещает курсор в конец EditText. В основном editText.getText().length()дает длину текста. Затем используйте setSelectionдлину.

editText.setSelection(0);

Он предназначен для установки курсора в начальную позицию (0).

7

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

Hello Try This

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

0
6

Если вы хотите выделить весь текст и просто ввести новый текст вместо старого, вы можете использовать

    android:selectAllOnFocus="true"
6

Это работает

Editable etext = edittext.getText();
Selection.setSelection(etext,edittext.getText().toString().length());
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"/>

@ строка / количество = "0.00" @ строка / 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) {

            }
        });

Надеюсь, это поможет!

4

Для ViewModel, LiveData и привязки данных

Мне нужна эта функция для EditTextподдержки многострочного приложения в моем приложении для заметок. Мне нужен курсор в конце текста, когда пользователь переходит к фрагменту с текстом заметки.

Решение, предложенное джлеопом, близко. Но проблема в том, что если пользователь помещает курсор где-нибудь в середине текста для редактирования и начинает печатать, курсор снова переместится в конец текста. Это произошло из-за того, что 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
}

Это решение, которое мне подходит и обеспечивает хороший пользовательский интерфейс. Надеюсь, это поможет и в ваших проектах.

1
  • 1
    Этот ответ должен быть выше. Огромное спасибо 25 окт.
3

похоже на ответ @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;
    }
});
3

Это безопасно :

    editText.setText("");
    if (!TextUtils.isEmpty(text)) {
        editText.append(text);
    }
3
etSSID.setSelection(etSSID.getText().length());
0
3

Приведенные выше ответы не сработали для меня. Итак, я нашел новое решение. Это может быть кому-то полезно. Я использую последнюю версию Android Studio, т.е. 3.5 на текущий момент. Может быть, это может быть причиной того, что приведенные выше ответы не дали никакого эффекта.

КОД:

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

Здесь 1-й аргумент - это текстовое значение Spannable, которое вы хотите воспроизвести, а 2-й аргумент - это значение индекса. Поскольку нам нужен курсор в конце текста, мы взяли getText (). Length (), который возвращает длину текста.

1
  • 1
    Не за что! Удачного кодирования! 30 дек '19 в 7:52
2
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-файле, это сработает. Я проверил это, и у меня это работает.

2

Если вы хотите поместить курсор в конец текста в режиме EditText

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