ChatGPT解决这个技术问题 Extra ChatGPT

将光标放在 EditText 中文本的末尾

我正在更改 keyListenerEditText 的值。

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

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

我遇到了同样的问题。但我更好地问自己为什么会发生这种情况,以便我可以提前解决问题,而不必自己移动插入符号。
@kaneda 我完全同意,但是如果您添加了实际的解决方案会很有帮助。
@Zainodis 这只是一个想法。就像我说的我遇到了同样的问题,这并不一定意味着我已经找到了解决方案。就我而言,我遇到了将 EditText 作为 ListView 的项目的问题。至于实验,我对 ListView 源代码本身进行了一些更改,这是一个相当复杂的野兽,并在模拟器上进行了测试。它与组件进行的焦点控制管理有关。所以当然这不是我可以帮助我们朋友的解决方案。 :)
这在 OnFocusChanged 回调中不起作用。解决方案是将 setSelection 放在一个可运行对象中并在主线程上运行它。在这里查看stackoverflow.com/a/32156989/4514796

u
user924

尝试这个:

更新:

科特林:

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

爪哇:

editText.setSelection(editText.getText().length());

这在我的情况下不起作用。 setSelection() 方法似乎没有效果。我的 EditText 视图包含 ImageSpans。还有其他一些解决方法吗?
@marqss,我遇到了同样的问题,对我来说工作得很好。我在对话框上使用 EditText 并从主屏幕预填充文本。发生这种情况时,光标停留在开头而不是结尾,但是在我尝试了您的建议之后,一切都很好,就像我想要的那样。感谢您发布此信息。
嘿@Mullay,我现在通过覆盖 EditText 类的 onSelectionChanged() 方法来处理它: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); }
您可能必须使用 et.post( new Runnable({... et.setSel... 才能进入队列。这是因为 android 等待做一些布局的东西,直到通过发布更好的时间,所以如果您尝试 setSelection在系统完成之前,它将撤消您的工作。
它在这里工作,感谢您的回答。但是您应该这样做:editText.setText(s); editText.setSelection(editText.getText().length()); //在setText之后
J
James

有一个名为 append 的函数用于 ediitext,它将字符串值附加到当前的 edittext 值并将光标放在值的末尾。您可以将字符串值作为当前 ediitext 值本身并调用 append();

myedittext.append("current_this_edittext_string"); 

如果您的 EditText 中已有文本,只需编写 myedittext.append("");
@ymerdrengene 只是申请 myedittext.append(""); 对我没有用!
这是完美的,因为它只是替换了我的代码行。正在使用 edittextfield.setText 并将其交换为追加。很简单。
取决于使用情况是否有效。对我来说没有。使用 Selection 是实现该 IMO 的正确方法。
v
vovahost

科特林:

将光标设置到起始位置:

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

可以用 findViewById<EditText>(R.id.edittext_id) 替换 findViewById(R.id.edittext_id) as EditText 或者如果使用 API 26+ 则避免强制转换
L
Lukas Niessen

如果您之前调用了 setText 并且新文本没有在由 View.post(Runnable) 触发的单独可运行文件中获得布局阶段调用 setSelection(从 this 主题重新发布)。

所以,对我来说,这段代码有效:

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

编辑 05/16/2019:现在我正在为此使用 Kotlin 扩展:

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

然后 - editText.placeCursorToEnd()。


谢谢这真的对我有用。我试图调用 setSelection 但它不起作用。在我的例子中,我试图设置一个固定的前缀来编辑文本,所以在设置前缀之后,我需要将光标设置到前缀的末尾,以便用户可以在前缀之后输入数据。由于我在 TextWatcher 的构造函数中执行 setSelection,可能这就是它不起作用的原因。但是您的解决方案效果很好!
我在我的 MultiAutoCompleteTextView 的 Clickablespan 方法中使用了这个 post 方法,它可以工作......一旦单击文本范围中的删除图标,我希望光标在末尾移动......它适用于所有最新的 android 手机。 ..但在旧版本中,第一次点击后需要一些时间......我所有其他项目都无法点击......任何线索?
我不知道为什么,但这是唯一对我有用的!我的编辑文本有一个焦点/文本更改侦听器,并包含在 TextInputLayout 中。其中一件事就是搞砸了。
E
Etienne Lawlor

您还可以将光标放在 EditText 视图中的文本末尾,如下所示:

EditText et = (EditText)findViewById(R.id.textview);
int textLength = et.getText().length();
et.setSelection(textLength, textLength);

k
kartikmaji
editText.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        editText.setSelection(editText.getText().length());
        return false;
    }
});

K
Kreshnik

这是另一种可能的解决方案:

et.append("");

如果由于任何原因不起作用,请尝试此解决方案:

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

I
Igor Siqueira

就我而言,我创建了以下 kotlin 分机。功能,可能对某人有用

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

然后如下使用

mEditText.focus()

tnx。请求重点很棒。
L
Leonid Ustenko

如果您的 EditText 不清楚:

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

或者

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

R
Rahul

您应该能够在 EditText's 方法 setSelection() 的帮助下实现这一点,请参阅 here


P
Praxis Ashelin
/**
 * 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);

它对我有用!


L
Li Che

我认为这可以实现你想要的。

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

如果我的观察是正确的,这会为每个小部件生成一个 android.widget.TextView$IClipboardDataPasteEventImpl 的实例。我最终得到了很多。显然它们最终会被清理掉,但似乎会增加内存消耗。我有一个对话框的 12 个实例,它是唯一的支配者(保持它活着的东西)是上面提到的实例。
将该段代码放置在代码中的适当位置(您将文本直接附加到 EText)。谢谢!
d
djleop

这个问题已经过时了,但我认为如果你想使用新发布的 Android 数据绑定工具,得到这个答案可能会很有用,只需在你的 XML 中设置它:

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

K
Khemraj Sharma

editText.setSelection 是这里的魔力。基本上,选择使您可以将光标放在您想要的任何位置。

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

这会将光标置于 EditText 的末尾。基本上 editText.getText().length() 为您提供文本长度。然后将 setSelection 与长度一起使用。

editText.setSelection(0);

用于将光标设置在起始位置 (0)。


R
Rahul Patil

https://i.stack.imgur.com/hXSS6.png

你好试试这个

 <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光标


a
ar-g

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

    android:selectAllOnFocus="true"

S
Sk93

这有效

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

Y
Yogesh Umesh Vaity

对于 ViewModel、LiveData 和数据绑定

我需要在我的笔记应用程序中为 EditText 提供多行支持的此功能。当用户导航到具有注释文本的片段时,我希望光标位于文本的末尾。

djleop 建议的解决方案很接近。但是这样做的问题是,如果用户将光标放在文本中间的某个位置进行编辑并开始输入,光标会再次跳到文本的末尾。发生这种情况是因为 LiveData 会发出新值,并且光标会再次跳转到文本的末尾,导致用户无法在中间的某处编辑文本。

为了解决这个问题,我使用 MediatorLiveData 并使用标志只为其分配一次 String 的长度。这将导致 LiveData 仅读取一次值,即当用户导航到片段时。之后,用户可以将光标放在他们想要在那里编辑文本的任何地方。

视图模型

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,其中包含您在 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 类类似于 Google 的 Jose Alcérreca 编写的 SingleLiveEvent。我在这里用它来处理屏幕旋转。使用单个 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
}

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


这个答案需要提高。非常感谢
D
Daniel Almeida

我测试过的所有其他代码都不能正常工作,因为用户仍然可以将插入符号/光标放在字符串中间的任何位置(例如: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) {

            }
        });

希望能帮助到你!


k
kartikmaji

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

A
Alécio Carvalho

这可以安全地解决问题:

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

a
adiga
etSSID.setSelection(etSSID.getText().length());

k
kishna.147
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,这将起作用。我已经对此进行了测试,它对我有用。


M
Mujahid Khan

如果要将光标放在 EditText 视图中的文本末尾

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

P
Prajwal Waingankar

以上答案对我不起作用。所以我找到了一个新的解决方案。这可能对某人有帮助。截至目前,我一直在使用最新版本的 Android Studio 即 3.5。也许这可能是上述答案没有显示任何效果的原因。

代码:

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

在这里,第一个参数是您想要使用的 Spannable 文本值,而第二个参数是索引值。因为,我们希望光标在文本的末尾,所以我们使用 getText().length() 来返回文本的长度


我的荣幸!快乐编码!
D
DavidUps
editText.accessibilityDelegate = object : View.AccessibilityDelegate() {
    override fun sendAccessibilityEvent(host: View?, eventType: Int) {
        super.sendAccessibilityEvent(host, eventType)
        if (eventType == TYPE_VIEW_TEXT_SELECTION_CHANGED) {
            editText.setSelection(editText.length())
        }
    }
}