EditText nhiều dòng với nút Hành động xong


114

Có thể có một EditTextwidget với android:inputType="textMultiLine"bộ, và android:imeOptions="actionDone"cùng một lúc?

Tôi muốn một hộp chỉnh sửa nhiều dòng, với nút tác vụ trên bàn phím là Xong, không phải Enter (Vận chuyển trở lại), nhưng có vẻ như nó không hoạt động ..

Cảm ơn trước


Điều gì về việc thử một widget kết hợp với EditText nhiều dòng và một Nút kết hợp với nhau?
Subin Sebastian

Câu trả lời:


194

Sử dụng

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
editText.setRawInputType(InputType.TYPE_CLASS_TEXT);

và trong XML:

android:inputType="textMultiLine"

đối với tôi con trỏ sẽ vẫn hiển thị khi bàn phím gặp trục trặc, tôi cần thêm textField.setCursorVisible(false);vào bên trong mộtonEditorActionListener
Fonix

Hoạt động trên 4.2.2 và 7.1.1. Cảm ơn.
tehcpu

1
Hoạt động rất tốt ... Tôi đã đấu tranh để tìm ra nó. Câu trả lời này nên được đánh dấu là câu trả lời hay nhất
MFAL

7
tại sao điều này hoạt động trái ngược với thiết lập tất cả trong xml?
Andrew Steinmetz

1
Rất vất vả để tìm thông tin này. Nó vẫn đang hoạt động như một cái duyên!
Costin

51

Từ tài liệu android: ' "textMultiLine" Bàn phím văn bản thông thường cho phép người dùng nhập các chuỗi văn bản dài bao gồm dấu ngắt dòng (dấu xuống dòng) . 'Do đó, thuộc tính textMultiLine không thích hợp nếu bạn muốn có nút' Xong 'trên bàn phím.

Một cách đơn giản để nhận trường nhập nhiều dòng (trong trường hợp này là 3 dòng) với nút hoàn tất là sử dụng EditText với

android:lines="3" 
android:scrollHorizontally="false" 

Tuy nhiên, vì một số lý do, điều này chỉ hoạt động với tôi nếu tôi thực hiện các cài đặt này trong mã thay vì tệp bố cục (trong onCreate) bằng cách

TextView tv = (TextView)findViewById(R.id.editText);
if (tv != null) {
    tv.setHorizontallyScrolling(false);
    tv.setLines(3);
}

Tôi hy vọng điều này sẽ giúp ích cho ai đó, vì đã mất khá nhiều thời gian để tìm ra. Nếu bạn tìm thấy cách làm cho nó hoạt động từ tệp kê khai, vui lòng cho chúng tôi biết.


4
Tôi cũng xin đề nghị cố gắng maxLines()thay vì setLines()nếu bạn muốn tránh thay đổi chiều cao củaEditText
Daniel Smith

Tôi nghĩ rằng trong câu hỏi không được làm rõ rằng bạn nên đặt android: imeOptions với một giá trị như actionSend. Để hoàn thành câu trả lời này, tôi phải đặt android: singleLine = "true" ngay cả khi loại setMaxLines ghi đè nó bằng mã (không làm như vậy sẽ không cung cấp cho bạn khóa enter với ví dụ "Gửi"). Để nắm bắt hành động <Enter>, hãy kiểm tra câu trả lời đầu tiên từ stackoverflow.com/questions/5014219/… .
DNax

Xin lỗi, giải pháp thay thế tốt nhất mà tôi tìm thấy về việc chụp <Enter> là @earlcasper câu trả lời tại đây stackoverflow.com/questions/1489852/…
DNax

1
Điều này làm việc hoàn hảo cho tôi (sử dụng setMaxLines(3)) Cảm ơn rất nhiều!
laurencevs

1
Hoạt động như một sự quyến rũ: chỉ cần thêm android: imeOptions = "actionDone" android: inputType = "text" vào XML của bạn và xóa android: lines = "3" android: scrollHoriztrl = "false" khỏi XML
HannahCarney

24

Ví dụ làm việc! Tạo lớp EditText tùy chỉnh bên dưới hỗ trợ tính năng này và sử dụng lớp trong tệp xml. Mã làm việc:

package com.example;

import android.content.Context;
import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;

public class ActionEditText extends EditText
{
   public ActionEditText(Context context)
   {
       super(context);
   }

   public ActionEditText(Context context, AttributeSet attrs)
   {
       super(context, attrs);
   }

   public ActionEditText(Context context, AttributeSet attrs, int defStyle)
   {
       super(context, attrs, defStyle);
   }

   @Override
   public InputConnection onCreateInputConnection(EditorInfo outAttrs)
   {
       InputConnection conn = super.onCreateInputConnection(outAttrs);
       outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
       return conn;
   }
}

<com.example.ActionEditText
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:imeOptions="actionDone"
       android:inputType="textAutoCorrect|textCapSentences|textMultiLine" />

Điều này phù hợp với tôi, yêu cầu của tôi là tạo một văn bản chỉnh sửa phải có nhiều dòng cũng như phải có nút tiếp theo trên các phím mềm ............... vì vậy cảm ơn rất nhiều vì tôi đã làm trong phần chỉnh sửa văn bản, tôi đã thêm 2 dòng android: inputType = "textMultiLine" android: imeOptions = "actionNext" Và trong lớp tùy chỉnh ở trên, tôi đã làm: InputConnection conn = super.onCreateInputConnection (outAttrs); //outAttrs.imeOptions & = ~ EditorInfo.IME_FLAG_NO_ENTER_ACTION; outAttrs.imeOptions & = EditorInfo.IME_ACTION_NEXT; trả lại conn;
yash

Làm. Đã thử nghiệm trên Andorid 6.0.1.
AmiguelS

9

Để thực hiện việc này trong Kotlin (và cũng có thể tùy chọn áp dụng các cấu hình khác như textCapSentencesbạn có thể sử dụng chức năng mở rộng này:

// To use this, do NOT set inputType on the EditText in the layout
fun EditText.setMultiLineCapSentencesAndDoneAction() {
    imeOptions = EditorInfo.IME_ACTION_DONE
    setRawInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or InputType.TYPE_TEXT_FLAG_MULTI_LINE)
}

Sử dụng:

myEditText.setMultiLineCapSentencesAndDoneAction()

1
Hoạt động kể từ tháng 6 năm 2019! Cảm ơn :)
Rohan Taneja

Chìa khóa đối với tôi là sử dụng setRawInputTypethay vìsetInputType
Tamoxin

9

Tôi nghĩ đây là cách để bạn làm điều đó. Có android:inputType="textMultiLine", android:imeOptions="actionDone"làm cho chức năng chính nhập trở nên mơ hồ. Chỉ cần lưu ý rằng bạn có thể sử dụng android:lines="10"và có thể loại bỏ android:inputType="textMultiLine", nhưng tùy thuộc vào những gì bạn muốn đạt được đôi khi bạn chỉ cần android:inputType="textMultiLine"và không có sự thay thế cho nó.

EditText ed=new EditText(this);
ed.setOnKeyListener(new OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if(keyCode == KeyEvent.KEYCODE_ENTER){
                //do your stuff here
            }
            return false;
        }
});

Tôi đã sử dụng một số lượng tối đa cố định với android: lines = "10" , tôi nhận được nút ok trên bàn phím. Mẹo hay nếu người ta biết sẽ có bao nhiêu dòng, ví dụ với một tập hợp maxLength nhỏ.
sunadorer

Tôi muốn vô hiệu hóa Mã khóa # 66 có được không? Làm thế nào tôi có thể làm điều đó?
Adil Malik

1
tại sao keyCode == 66 thay vì keyCode == EditorInfo.IME_ACTION_GO?
tse

5

Điều này dường như làm việc hoàn hảo cho tôi

int lineNum = 2;
mEditText.setHorizontallyScrolling(false);
mEditText.setLines(3);

4

Giải pháp Kotlin có thể tái sử dụng

Đặt các giá trị này trong mã là điều duy nhất phù hợp với tôi

edittext.inputType = EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
edittext.setHorizontallyScrolling(false)
edittext.maxLines = Integer.MAX_VALUE // Or your preferred fixed value

Tôi yêu cầu điều này thường xuyên, vì vậy hãy làm điều này để giữ cho mã sạch:

fun EditText.multilineIme(action: Int) {
    imeOptions = action
    inputType = EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
    setHorizontallyScrolling(false)
    maxLines = Integer.MAX_VALUE
}

// Then just call
edittext.multilineIme(EditorInfo.IME_ACTION_DONE)

Nếu bạn muốn thêm một hành động tùy chỉnh tùy chọn vào 'Hoàn tất', hãy thử cách này:

fun EditText.multilineDone(callback: (() -> Unit)? = null) {
    val action = EditorInfo.IME_ACTION_DONE
    multilineIme(action)
    setOnEditorActionListener { _, actionId, _ ->
            if (action == actionId) {
                callback?.invoke()
                true
            }
            false
        }
    }
}

// Then you can call
edittext.multilineDone { closeKeyboard() }

// or just
edittext.multilineDone()

Bạn cần dễ dàng điều khiển bàn phím khi gọi lại? Đọc bài đăng này

Sau đó thêm hideKeyboard()cuộc gọi vàoEditText.multilineDone


1
☝️Đây là một câu trả lời tuyệt vời
Michael

3

Câu trả lời ngắn gọn: Không, tôi tin rằng không thể có trước API cấp 11 (3.0).

Vấn đề tương tự được cắt ra ở đây (thảo luận trong phần nhận xét cho câu trả lời được chấp nhận):

Nút tác vụ bàn phím mềm Android

Từ nhận xét cuối cùng:

Nhìn vào một số ứng dụng trên điện thoại của tôi, có vẻ như hộp nhiều dòng ở cuối cùng, với nút "Xong" hoặc "Gửi" hiển thị bên dưới (ví dụ: ứng dụng Email).


3

Một cách đơn giản để giải quyết tình huống này:

  • giữ các thuộc tính này trên EditText:

    android:inputType="textMultiLine" 
    android:scrollHorizontally="false"
  • sau đó thêm mã này để chỉ ẩn bàn phím khi nhấn ENTER:

    editText.setOnEditorActionListener(new OnEditorActionListener() 
    {
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) 
        {
            editText.setSelection(0);
            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);      
            return true;
         } 
         else 
         {
            return false;
         }
         }
    });

2

Nếu đó không phải là giao diện của bàn phím ảo, bạn có thể chỉ cần đặt một trình nghe đầu vào trên bàn phím và kích hoạt trạng thái "đã xong" nếu người dùng nhập dòng mới.


2

nếu bạn sử dụng tùy chọn đầu vào textImeMultiline với cờ imeoptions và actionnext, bạn sẽ nhận được một nút tiếp theo thay vì trả về cariage


2

Mặc dù không có giải pháp nào khác từng hiệu quả với tôi, nhưng giải pháp sau đây hoạt động tuyệt vời và giúp tôi tiết kiệm ngày này qua ngày khác cho việc tìm kiếm nhiều hơn trên Google, tất nhiên là với một vài thao tác của riêng tôi. Thật không may, tôi không nhớ chính xác nơi tôi lấy mã từ đâu và vì vậy không thể cung cấp cho tác giả tín dụng mà anh ấy / cô ấy rất xứng đáng.

Trong mã Java của bạn:

////////////Code to Hide SoftKeyboard on Enter (DONE) Press///////////////
editText.setRawInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
editText.setImeActionLabel("DONE",EditorInfo.IME_ACTION_DONE);              //Set Return Carriage as "DONE"
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) 
    {
                if (event == null) {
                    if (actionId == EditorInfo.IME_ACTION_DONE) {
                        // Capture soft enters in a singleLine EditText that is the last EditText
                        // This one is useful for the new list case, when there are no existing ListItems
                        editText.clearFocus();
                        InputMethodManager inputMethodManager = (InputMethodManager)  getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
                        inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
                    }

                    else if (actionId == EditorInfo.IME_ACTION_NEXT) {
                        // Capture soft enters in other singleLine EditTexts
                    } else if (actionId == EditorInfo.IME_ACTION_GO) {
                    } else {
                        // Let the system handle all other null KeyEvents
                        return false;
                    }
                } 
        else if (actionId == EditorInfo.IME_NULL) {
                    // Capture most soft enters in multi-line EditTexts and all hard enters;
                    // They supply a zero actionId and a valid keyEvent rather than
                    // a non-zero actionId and a null event like the previous cases.
                    if (event.getAction() == KeyEvent.ACTION_DOWN) {
                        // We capture the event when the key is first pressed.
                    } else {
                        // We consume the event when the key is released.
                        return true;
                    }
                } 
        else {
                    // We let the system handle it when the listener is triggered by something that
                    // wasn't an enter.
                    return false;
                }
                return true;
        }
});




1

Tôi đang sử dụng 4.x và đã thử gọi setHorizosystemScrolling () (có hoặc không có setLine () hoặc setMaxLines ()), cũng như nhiều cấu hình XML khác nhau để hiển thị nút Xong. Không ai trong số họ làm việc. Điểm mấu chốt là nếu EditText của bạn là nhiều dòng, Android sẽ luôn muốn hiển thị ký tự xuống dòng thay vì nút "Xong", trừ khi bạn đưa ra một số thủ thuật xung quanh vấn đề này.

Giải pháp ít phức tạp nhất mà tôi tìm thấy mà không liên quan đến việc ánh xạ lại hành vi của dấu xuống dòng là ở đây: https://stackoverflow.com/a/12570003/3268329 . Giải pháp này sẽ vô hiệu hóa mong muốn không ngừng của Android để buộc cài đặt cờ IME_FLAG_NO_ENTER_ACTION cho các chế độ xem nhiều dòng, điều này khiến nút Xong biến mất.


0

Tôi cũng đã đấu tranh trong một thời gian khá dài, nhưng cuối cùng tôi đã tìm ra giải pháp!

Chỉ cần tạo một lớp EditText tùy chỉnh như sau:

public class EditTextImeMultiline extends EditText {

    public void init() {
        addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                for (int i = s.length(); i > 0; i--)
                    if (s.subSequence(i - 1, i).toString().equals("\n"))
                        s.replace(i - 1, i, "");
            }
        });
        setSingleLine();
        setHorizontallyScrolling(false);
        this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                EditTextImeMultiline.this.setLines(EditTextImeMultiline.this.getLineCount());
            }
        });
    }

    public EditTextImeMultiline(Context context) {
        super(context);
        init();
    }

    public EditTextImeMultiline(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }
}

Lớp này loại bỏ lineBreaks (\ n), bao bọc văn bản như textMultiline sẽ làm, VÀ cho phép bạn thay thế nút Enter bằng một ImeAction;).

Bạn chỉ cần gọi nó trong XML của mình thay vì lớp EditText cổ điển.

Để giải thích logic ở đây:

  • Đặt EditText dưới dạng singleLine để có thể hiển thị nút ImeAction thay vì Enter.
  • Loại bỏ cuộn ngang để làm cho văn bản chuyển sang dòng tiếp theo khi đến cuối dạng xem.
  • Xem các thay đổi về bố cục với onGlobalLayoutListener và đặt tham số "dòng" thành "số dòng" của văn bản hiện tại được giữ bởi editText. Đây là những gì làm mới chiều cao của nó.

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.