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


884

Я меняю значение в положение EditTextON keyListener.

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

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


3
Я столкнулся с той же проблемой. Но я лучше спросил себя, почему это происходит, чтобы я мог решить проблему раньше, чем самому перемещать каретку.
Канеда

3
@kaneda Я полностью согласен, однако было бы полезно, если бы вы добавили фактическое решение.
AgentKnopf

1
@Zainodis Это была просто мысль. Как я уже говорил, я столкнулся с той же проблемой, что не обязательно означает, что я нашел решение. В моем случае у меня была проблема с EditTexts как пунктами a ListView. Что касается экспериментов, я внес некоторые изменения в сам ListViewисходный код, довольно сложный зверь, и протестирован на эмуляторе. Это было связано с управлением фокусом, сделанным компонентом. Поэтому, конечно, это не решение, которое я мог бы дать, чтобы помочь нашему другу. :)
Канеда


Это не работает внутри OnFocusChangedобратного вызова. Решение заключается в том, чтобы поместить setSelection в исполняемый файл и запустить его в главном потоке. Проверьте здесь stackoverflow.com/a/32156989/4514796
Али Нем

Ответы:


1320

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

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

15
Это не работает в моем случае. Метод setSelection (), кажется, не имеет никакого эффекта. Мое представление EditText содержит ImageSpans. Есть ли другой вид обходного решения?
toobsco42

@marqss, у меня была такая же проблема, и она отлично сработала. Я использовал EditText в диалоге и предварительно заполнял текст с главного экрана. Когда это происходит, курсор остается в начале, а не в конце, но после того, как я попробовал ваше предложение, все в порядке, как я и хотел. Спасибо за публикацию.
Винси

4
Привет @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); }
toobsco42

19
Возможно, вам придется использовать et.post (new Runnable ({... et.setSel ..., чтобы попасть в очередь). Это потому, что android ждет, пока что-то сделает макет, до лучшего времени, отправив сообщение, поэтому, если вы попытаетесь установить setSelection прежде чем система будет завершена, она
отменит

1
Это работает здесь, спасибо за ваш ответ. Но вы должны сделать так: editText.setText (s); editText.setSelection (editText.getText () длина ().); // после setText
smileVann

224

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

myedittext.append("current_this_edittext_string"); 

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

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

4
Это идеально, потому что он просто заменяет строку кода, которую я имел. Использовал edittextfield.setText и просто поменял его на добавление. Очень просто.
Theblitz

Зависит от использования, если это работает или нет. Для меня это не так. Использование Selectionявляется правильным способом достижения этой ИМО.
sud007

140

Котлин :

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

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_

98

Если вы звонили setTextраньше, и новый текст не получил вызов фазы макета setSelectionв отдельном запускаемом файле View.post(Runnable)(репост из этой темы).

Итак, для меня этот код работает:

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

Изменить 16.05.2009: Прямо сейчас я использую расширение Kotlin для этого:

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

а затем - editText.placeCursorToEnd ().


Спасибо, это действительно сработало для меня. Я пытался вызвать setSelection, но это не сработает. В моем случае я пытался установить фиксированный префикс для редактирования текста, и поэтому после установки префикса мне нужно было установить курсор на конец префикса, чтобы пользователь мог вводить данные после префикса. Так как я делал setSelection в конструкторе TextWatcher, возможно, поэтому он не работал. Но ваше решение сработало отлично!
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 не понятен:

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

или

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

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

            }
        });

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


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

Здесь 1-й аргумент - это текстовое значение Spannable, которое вы хотите воспроизвести, тогда как 2-й аргумент - это значение индекса. Поскольку нам нужен курсор в конце текста, мы взяли 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.