我正在更改keyListener上的EditText的值。

但是当我更改文本时,光标移动到EditText的开头。 我需要光标在文本的末尾。

如何将光标移动到EditText文本的末尾。


当前回答

这个问题已经很老了,但我认为如果你想使用Android上最新发布的DataBinding工具,有这个答案可能会很有用,只需在XML中设置这个:

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

其他回答

如果你的EditText不清楚:

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

or

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

如果你想选择所有文本,只是输入新的文本而不是旧的,你可以使用

    android:selectAllOnFocus="true"
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) {

    }
}

在XML文件中使用此CustomEditText,这将起作用。我已经测试过了,它对我很有效。

用于ViewModel, LiveData和Data绑定

我需要这个功能的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
        }
    }
}

在这里,youobjecject是从数据库检索到的另一个LiveData,该数据库包含您在EditText中显示的String文本。

然后使用绑定适配器将此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类类似于由Jose Alcérreca从谷歌编写的SingleLiveEvent。我在这里使用它来处理屏幕旋转。使用单个事件将确保当用户编辑文本在中间的某个地方并且屏幕旋转时,光标不会跳到文本的末尾。当屏幕旋转时,它将保持相同的位置。

下面是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
}

这是适合我的解决方案,提供了良好的用户体验。希望它对你的项目也有帮助。

类似于@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;
    }
});