Многострочный EditText с кнопкой "Готово"

Возможно ли иметь виджет EditText с android:inputType="textMultiLine" и android:imeOptions="actionDone" в то же время?

Мне нужно многострочное окно редактирования, при этом кнопка действия на клавиатуре будет выполнена, а не Enter (возврат каретки), но она, похоже, не работает.

Заранее спасибо

Ответ 1

Используйте

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

и в XML:

android:inputType="textMultiLine"

Ответ 2

Из документации по android: ' "textMultiLine"   Обычная текстовая клавиатура, которая позволяет пользователям вводить длинные строки текста, содержащие разрывы строк (возврат каретки). ' Поэтому атрибут textMultiLine не подходит, если вы хотите иметь кнопку "Готово" на клавиатуре.

Простой способ получить многострочное (в данном случае 3 строки) поле ввода с помощью сделанной кнопки - использовать EditText с

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

Однако по какой-то причине это работает только для меня, если я сделаю эти настройки в коде вместо файла макета (в onCreate) на

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

Я надеюсь, что это поможет кому-то, так как потребовалось довольно много времени, чтобы разобраться. Если вы найдете способ заставить его работать из манифеста, сообщите нам об этом.

Ответ 3

Рабочий пример! Создайте следующий пользовательский класс EditText, который поддерживает эту функцию, и используйте класс в XML файле. Рабочий код:

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

Ответ 4

Я думаю, что это способ сделать то, что вам нужно. Имея android:inputType="textMultiLine", android:imeOptions="actionDone" делает android:imeOptions="actionDone" функциональность ввода ключа. Просто имейте в виду, что вы можете использовать android:lines="10" и, возможно, удалить android:inputType="textMultiLine", но зависит от того, чего вы хотите достичь, иногда вам просто нужен android:inputType="textMultiLine" и нет замены для этого.

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

Ответ 5

Это, кажется, отлично работает для меня.

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

Ответ 6

Короткий ответ: Нет, я считаю, что это невозможно до уровня API 11 (3.0).

Эта же проблема возникла здесь (обсуждается в комментариях к принятому ответу):

Кнопка Android Soft для клавиатуры

Из заключительного комментария:

Если посмотреть на несколько приложений на моем телефоне, кажется, что для этого есть многострочный блок с видимой надписью "Готово" или "Отправить" (например, приложение электронной почты).

Ответ 7

Если речь идет не о внешнем виде экранной клавиатуры, вы можете просто добавить слушателя на клавиатуру и запустить "done" -status, если пользователь вводит новую строку.

Ответ 8

если вы используете параметр ввода textImeMultiline с помощью imeoptions flagnext и actionnext, вы получаете следующую кнопку вместо возврата кариеса

Ответ 9

Я на 4.x и попытался вызвать setHorizontallyScrolling() (с или без setLine() или setMaxLines()), а также множество различных конфигураций XML, чтобы показать кнопку Готово. Ни один из них не работал. Суть в том, что если ваш EditText является многострочным, Android всегда будет хотеть показывать возврат каретки вместо кнопки "Готово", если вы не вложите в нее какой-то хак.

Самое меньшее решение для осложнений, которое я обнаружил, не включает переназначение поведения возврата каретки: fooobar.com/questions/20296/.... Это решение аннулирует нежелательное желание Android принудительно установить флаг IME_FLAG_NO_ENTER_ACTION для многострочных представлений, что приводит к исчезновению кнопки "Готово".

Ответ 10

Простой способ обойти эту ситуацию:

  • сохраните эти атрибуты в EditText:

    android:inputType="textMultiLine" 
    android:scrollHorizontally="false"
    
  • затем добавьте этот код, чтобы скрыть клавиатуру только при нажатии 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;
         }
         }
    });
    

Ответ 11

Я слишком долго боролся, но наконец нашел решение!

Просто создайте собственный класс EditText как таковой:

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

Этот класс удаляет lineBreaks (\n), обертывает текст, как textMultiline, и позволяет вам заменить кнопку Enter на ImeAction;).

Вам просто нужно вызвать его в XML вместо классического класса EditText.

Чтобы объяснить логику здесь:

  • Установите EditText как singleLine, чтобы показывать кнопку ImeAction вместо Enter.
  • Удалите горизонтальную прокрутку, чтобы текст переместился на следующую строку при достижении конца представления.
  • Просмотрите изменения компоновки с помощью onGlobalLayoutListener и установите параметр "line" в "lineCount" текущего текста, хранящегося в файле editText. Это то, что освежает его высоту.

Ответ 12

Рабочее решение здесь, создайте свой собственный EditTextView (просто расширьте текстовое представление) и переопределите onInputConnection с частью кода, который вы найдете в принятом ответе здесь: Многострочный EditText с Done SoftInput Action Label на 2.3

Ответ 13

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

В коде Java:

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

Ответ 14

Пример функции расширения Kotlin для включения действия Done и конкретной комбинации типов ввода в EditTextExt.kt:

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

Затем использование:

myEditText.setMultiLineCapSentencesAndDoneAction()

Ответ 15

Чтобы сделать это в Kotlin (а также, возможно, примените другие конфигурации, такие как textCapSentences вы можете использовать эту функцию расширения:

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

Использование:

myEditText.setMultiLineCapSentencesAndDoneAction()

Ответ 16

Простой способ обойти эту ситуацию:

изменить атрибуты в EditText:

android:inputType="textMultiLine"
android:scrollHorizontally="false"

в

android:inputType="textImeMultiLine"
android:scrollHorizontally="false"