Đặt con trỏ ở cuối văn bản trong EditText


883

Tôi thay đổi giá trị của một EditTextngày keyListener.

Nhưng khi tôi thay đổi văn bản, con trỏ sẽ di chuyển đến đầu của EditText. Tôi cần con trỏ ở cuối văn bản.

Cách di chuyển con trỏ đến cuối văn bản trong a EditText.


3
Tôi đã gặp vấn đề tương tự. Nhưng điều tôi tự hỏi mình tốt hơn là tại sao điều này lại xảy ra, để tôi có thể giải quyết vấn đề trước đó thay vì phải tự mình di chuyển.
kaneda

3
@kaneda Tôi hoàn toàn đồng ý, tuy nhiên sẽ rất hữu ích nếu bạn thêm giải pháp thực tế.
Đặc vụKnopf

1
@Zainodis Đó chỉ là một ý nghĩ. Giống như tôi đã nói tôi gặp phải vấn đề tương tự, điều đó không nhất thiết có nghĩa là tôi đã tìm ra giải pháp. Trong trường hợp của tôi, tôi có vấn đề với các EditTextmục của a ListView. Đối với thử nghiệm, tôi đã thực hiện một số thay đổi trên chính ListViewmã nguồn, đây là một con thú khá phức tạp và được thử nghiệm trên trình giả lập. Nó liên quan đến quản lý kiểm soát tập trung được thực hiện bởi các thành phần. Vì vậy, tất nhiên đó không phải là giải pháp tôi có thể đưa ra để giúp bạn mình. :)
kaneda


Điều này không hoạt động trong OnFocusChangedcuộc gọi lại. Giải pháp là đặt setSelection bên trong một runnable và chạy nó trên luồng chính. Kiểm tra tại đây stackoverflow.com/a/32156989/4514796
Ali Nem

Câu trả lời:


1319

Thử cái này:

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

15
Điều này không làm việc trong trường hợp của tôi. Phương thức setSelection () dường như không có hiệu lực. Giao diện EditText của tôi chứa ImageSpans. Có một số cách giải quyết khác?
toobsco42

@marqss, tôi có cùng một vấn đề và làm việc hoàn hảo cho tôi. Tôi đã sử dụng EditText trên Hộp thoại và nhập văn bản từ màn hình chính. Khi điều đó xảy ra, con trỏ vẫn ở đầu và không ở cuối nhưng sau khi tôi thử đề xuất của bạn, mọi thứ đều ổn, theo cách tôi muốn. Cảm ơn vì đã đăng tải điều này.
Vincy

4
Xin chào @Mullay, tôi hiện đang xử lý nó bằng cách ghi đè onSelectionChanged()phương thức của một EditTextlớp: 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
Bạn có thể phải sử dụng et.post (Runnable mới ({... et.setSel ... để vào hàng đợi. Điều này là do android chờ để thực hiện một số công cụ bố cục cho đến thời điểm tốt hơn bằng cách đăng bài vì vậy nếu bạn cố gắng đặtSelection trước khi hệ thống kết thúc, nó sẽ hoàn tác công việc của bạn.
MinceMan

1
Nó hoạt động ở đây, cảm ơn câu trả lời của bạn. Nhưng bạn nên làm như thế này: editText.setText (s); editText.setSelection (editText.getText (). length ()); // sau setText
smileVann 30/03/2016

224

Có một hàm gọi là append cho ediitext, nối thêm giá trị chuỗi vào giá trị edittext hiện tại và đặt con trỏ ở cuối giá trị. Bạn có thể có giá trị chuỗi như chính giá trị ediitext hiện tại và gọi append ();

myedittext.append("current_this_edittext_string"); 

1
Nếu bạn đã có văn bản trong EditText của mình, chỉ cần viếtmyedittext.append("");
ymerdrengene

4
@ymerdrengene chỉ áp dụng myedittext.append("");đã không làm việc cho tôi!
Chintan Shah

4
Điều này là hoàn hảo bởi vì nó chỉ đơn giản là thay thế dòng mã tôi đã có. Đã sử dụng edittextfield.setText và chỉ cần hoán đổi nó để chắp thêm. Rất đơn giản.
theblitz

Phụ thuộc vào việc sử dụng nếu điều đó làm việc hay không. Đối với tôi thì không. Sử dụng Selectionlà cách chính xác để đạt được IMO đó.
sud007

140

Kotlin :

đặt con trỏ đến vị trí bắt đầu :

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

đặt con trỏ ở cuối phần Chỉnh sửa :

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

Mã bên dưới là đặt con trỏ sau ký tự thứ hai:

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

JAVA :

đặt con trỏ đến vị trí bắt đầu :

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

đặt con trỏ ở cuối phần Chỉnh sửa :

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

Mã bên dưới là đặt con trỏ sau ký tự thứ hai:

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

1
Có thể thay thế findViewById(R.id.edittext_id) as EditTextbằng findViewById<EditText>(R.id.edittext_id)hoặc chỉ tránh việc truyền nếu sử dụngAPI 26+
Evin1_

97

Nếu bạn gọi setTexttrước và các văn bản mới đã không nhận được bố trí giai đoạn cuộc gọi setSelectiontrong một Runnable riêng sa thải bởi View.post(Runnable)(repost từ này chủ đề).

Vì vậy, đối với tôi mã này hoạt động:

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

Chỉnh sửa 16/05/2019: Hiện tại tôi đang sử dụng tiện ích mở rộng Kotlin cho điều đó:

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

và sau đó - editText.placeC ruộngToEnd ().


Cảm ơn điều này thực sự làm việc cho tôi. Tôi đã cố gắng gọi setSelection nhưng nó không hoạt động. Trong trường hợp của tôi, tôi đã cố gắng đặt tiền tố cố định để chỉnh sửa văn bản và vì vậy sau khi đặt tiền tố, tôi cần đặt con trỏ ở cuối tiền tố để người dùng có thể nhập dữ liệu sau tiền tố. Vì tôi đang thực hiện setSelection trong hàm tạo của TextWatcher, có thể đó là lý do tại sao nó không hoạt động. Nhưng giải pháp của bạn đã làm việc tuyệt vời!
Wand Maker

Tôi đang sử dụng phương thức đăng bài này trong phương thức Clickablespan của MultiAutoCompleteTextView và nó hoạt động ..... Tôi muốn con trỏ di chuyển ở cuối khi biểu tượng xóa trong khoảng văn bản được nhấp vào ... Nó hoạt động trong tất cả các điện thoại di động Android mới nhất. ..nhưng trong các phiên bản cũ, phải mất một thời gian sau lần nhấp đầu tiên ... tất cả các mục khác của tôi không thể nhấp được ... có manh mối nào không ??
VijayRaj

1
Tôi không biết tại sao, nhưng đây là người duy nhất làm việc cho tôi! Văn bản chỉnh sửa của tôi có một trình nghe thay đổi tiêu điểm / văn bản và được gói trong TextInputLayout. Một trong những điều đó đang làm rối tung nó lên.
Daniel Wilson

42

Bạn cũng có thể đặt con trỏ ở cuối văn bản trong EditTextchế độ xem như sau:

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

Đây là một giải pháp khả thi khác:

et.append("");

Chỉ cần thử giải pháp này nếu nó không hoạt động vì bất kỳ lý do nào:

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

Nó làm việc tốt cho tôi!


12

Trong trường hợp của tôi, tôi đã tạo ra ext kotlin sau. chức năng, có thể hữu ích cho ai đó

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

Sau đó sử dụng như sau

mEditText.focus()

12

Nếu EditText của bạn không rõ ràng:

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

hoặc là

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

12

Bạn sẽ có thể đạt được điều đó với sự trợ giúp của EditText'sphương pháp setSelection(), xem tại đây


10

Tôi nghĩ rằng điều này có thể đạt được những gì bạn muốn.

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

Nếu các quan sát của tôi là chính xác, điều này sẽ sinh ra một thể hiện của android.widget.TextView $ IClipboardDataPasteEventImpl cho mỗi tiện ích. Tôi đã kết thúc với hàng tấn của họ. Rõ ràng cuối cùng họ được dọn dẹp, nhưng dường như làm tăng mức tiêu thụ bộ nhớ. Tôi đã có 12 trường hợp của một hộp thoại, đó chỉ là người thống trị (những gì giữ cho nó tồn tại) là trường hợp được đề cập ở trên.
Đặc vụKnopf

Đặt đoạn mã đó vào vị trí thích hợp trong mã (nơi bạn đang nối văn bản trực tiếp vào EText). Cảm ơn!
sud007

9

Câu hỏi đã cũ và đã được trả lời, nhưng tôi nghĩ có thể hữu ích khi có câu trả lời này nếu bạn muốn sử dụng các công cụ DataBinding mới phát hành cho Android, chỉ cần đặt câu hỏi này trong XML của bạn:

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

6

nhập mô tả hình ảnh ở đây

Xin chào thử cái này

 <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 pointcon trỏ


5

Nếu bạn muốn chọn tất cả văn bản và chỉ cần nhập văn bản mới thay vì văn bản cũ, bạn có thể sử dụng

    android:selectAllOnFocus="true"

5

Những công việc này

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

5

editText.setSelectionlà ma thuật ở đây. Về cơ bản lựa chọn cung cấp cho bạn đặt con trỏ ở bất kỳ vị trí nào bạn muốn.

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

Điều này đặt con trỏ đến cuối EditText. Về cơ bản editText.getText().length()cung cấp cho bạn chiều dài văn bản. Sau đó, bạn sử dụng setSelectionvới chiều dài.

editText.setSelection(0);

Nó là để thiết lập con trỏ ở vị trí bắt đầu (0).


4

Tất cả các mã khác mà tôi đã kiểm tra không hoạt động tốt do thực tế là người dùng vẫn có thể đặt dấu mũ / con trỏ ở bất cứ đâu ở giữa chuỗi (ví dụ: 12 | 3.00 - trong đó | là con trỏ). Giải pháp của tôi luôn đặt con trỏ ở cuối chuỗi bất cứ khi nào chạm vào EditText.

Giải pháp cuối cùng là:

// 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"/>

@ chuỗi / số tiền = "0,00" @ chuỗi / 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) {

            }
        });

Hy vọng nó giúp!


3

Đối với ràng buộc ViewModel, LiveData và dữ liệu

Tôi cần chức năng này EditTextvới sự hỗ trợ đa dòng trong ứng dụng ghi chú của tôi. Tôi muốn con trỏ ở cuối văn bản khi người dùng điều hướng đến đoạn có văn bản ghi chú.

Các giải pháp được đề xuất bởi djleop đến gần. Nhưng vấn đề với điều này là, nếu người dùng đặt con trỏ ở đâu đó ở giữa văn bản để chỉnh sửa và bắt đầu nhập, con trỏ sẽ lại nhảy đến cuối văn bản. Điều này xảy ra vìLiveData sẽ phát ra giá trị mới và con trỏ sẽ nhảy đến cuối văn bản một lần nữa dẫn đến việc người dùng không thể chỉnh sửa văn bản ở đâu đó ở giữa.

Để giải quyết điều này, tôi sử dụng MediatorLiveDatavà gán cho nó độ dài Stringchỉ một lần bằng cách sử dụng cờ. Điều này sẽ khiến LiveData chỉ đọc giá trị một lần, nghĩa là khi người dùng điều hướng đến đoạn. Sau đó, người dùng có thể đặt con trỏ bất cứ nơi nào họ muốn chỉnh sửa văn bản ở đó.

ViewModel

private var accessedPosition: Boolean = false

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

Đây yourObjectlà một LiveData khác được lấy từ cơ sở dữ liệu chứa văn bản Chuỗi mà bạn đang hiển thị trong EditText.

Sau đó liên kết nó MediatorLiveDatavới EditText của bạn bằng cách sử dụng bộ điều hợp liên kết.

XML

Sử dụng ràng buộc dữ liệu hai chiều để hiển thị văn bản cũng như chấp nhận nhập văn bản.

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

Bộ điều hợp đóng sách

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

Event lớp học

Các Eventlớp học ở đây cũng giống như một SingleLiveEvent được viết bởi Jose Alcérreca từ Google. Tôi sử dụng nó ở đây để chăm sóc xoay màn hình. Sử dụng một lần duy nhất Eventsẽ đảm bảo rằng con trỏ sẽ không nhảy đến cuối văn bản khi người dùng đang chỉnh sửa văn bản ở đâu đó ở giữa và màn hình xoay. Nó sẽ duy trì cùng một vị trí khi màn hình xoay.

Đây là Eventlớp học:

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
}

Đây là giải pháp phù hợp với tôi và cung cấp trải nghiệm người dùng tốt. Hy vọng nó sẽ giúp trong các dự án của bạn quá.


Câu trả lời này cần phải được đưa lên. Rất cám ơn
Abdul Rahman Shamair

2

tương tự như câu trả lời của @Anh Duy, nhưng nó không hoạt động với tôi. tôi cũng cần con trỏ chỉ di chuyển đến cuối khi người dùng chạm vào văn bản chỉnh sửa và vẫn có thể chọn vị trí của con trỏ sau đó, đây là mã duy nhất hoạt động với tôi

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

Đây là mẹo an toàn :

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


2

Các câu trả lời trên không làm việc cho tôi. Vì vậy, tôi tìm ra một giải pháp mới. Điều này có thể hữu ích cho một ai đó. Tôi đã sử dụng phiên bản Android Studio mới nhất tức là 3.5 theo ngày hiện tại. Có lẽ đó có thể là lý do y các câu trả lời trên không cho thấy hiệu quả.

MÃ:

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

Ở đây, đối số thứ nhất là giá trị văn bản Spannable mà bạn muốn phát trong khi đối số thứ 2 là giá trị chỉ mục. Vì, chúng tôi muốn con trỏ ở cuối văn bản, chúng tôi đã lấy getText (). Length () trả về độ dài của văn bản


1
Hân hạnh! Chúc mừng mã hóa!
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) {

    }
}

Sử dụng CustomEditText này trong tệp XML của bạn, điều này sẽ hoạt động. Tôi đã thử nghiệm điều này và nó đang làm việc cho tôi.


1

Nếu bạn muốn đặt con trỏ ở cuối văn bản trong chế độ xem Chỉnh sửa

 EditText rename;
 String title = "title_goes_here";
 int counts = (int) title.length();
 rename.setSelection(counts);
 rename.setText(title);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.