Багаторядковий EditText за допомогою кнопки "Готово"


114

Чи можливо мати EditTextвіджет із android:inputType="textMultiLine"набором, і android:imeOptions="actionDone"одночасно?

Мені б хотілося, щоб у рядку редагування було багато рядків із кнопкою дії на клавіатурі Готово, а не Enter (Повернення перевезення), але це, здається, не працює ..

Спасибі заздалегідь


А як спробувати складений віджет із багаторядковим EditText та кнопкою, поєднаних разом?
Субін Себастьян

Відповіді:


194

Використовуйте

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

та в XML:

android:inputType="textMultiLine"

для мене курсор все одно буде показувати, коли клавіатура знизилася, мені потрібно було додати textField.setCursorVisible(false);всерединуonEditorActionListener
Fonix

Працює на 4.2.2 та 7.1.1. Дякую.
tehcpu

1
Працює дуже добре ... Я намагався її знайти. Цю відповідь слід позначити як найкращу відповідь
MFAL

7
чому це працює на відміну від налаштування цього у xml?
Ендрю Штейнмет

1
Напружившись, щоб знайти цю інформацію. Він як і раніше працює як шарм!
Костін

51

З документації на 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);
}

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


4
Я б також запропонував спробувати maxLines()замість цього, setLines()якщо ви хочете уникнути зміни висотиEditText
Даніель Сміт

Я думаю, що в питанні не з’ясовано, що вам слід встановити android: imeOptions зі значенням, таким як actionSend. Завершуючи цю відповідь, мені довелося встановити android: singleLine = "true", навіть якщо setMaxLines свого роду перезаписує його за кодом (якщо це не зробити, то не надасть вам ключ введення, наприклад, "Send"). Щоб зафіксувати дію <Enter>, перевірте першу відповідь від stackoverflow.com/questions/5014219/… .
DNax

До жаль, кращий варіант я знайшов про захоплення <Введення> є @earlcasper відповідь тут stackoverflow.com/questions/1489852 / ...
DNax

1
Це прекрасно працювало для мене (використовуючи setMaxLines(3)) Дякую!
лавренцев

1
Працює як шарм: просто додайте android: imeOptions = "actionDone" android: inputType = "текст" у ваш XML, а також видаліть android: lines = "3" android: scrollHorizontally = "false" з XML
HannahCarney

24

Робочий приклад! Створіть нижче спеціальний клас 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" />

Це працювало для мене, моя вимога полягала в тому, щоб зробити текст редагування, який повинен бути багаторядковим, а також має бути наступна кнопка на програмних клавішах ............... тому велике спасибі, що я зробив в редагуванні тексту я додав 2 рядки android: inputType = "textMultiLine" android: imeOptions = "actionNext". І в користувацькому класі вище я зробив: InputConnection conn = super.onCreateInputConnection (outAttrs); //outAttrs.imeOptions & = ~ EditorInfo.IME_FLAG_NO_ENTER_ACTION; outAttrs.imeOptions & = EditorInfo.IME_ACTION_NEXT; повернути конн;
яш

Працює. Випробувано на Andorid 6.0.1.
AmiguelS

9

Для цього в Котліні (а також додатково застосувати інші конфігурації, наприклад, 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()

1
Працює станом на червень 2019 року! Дякую :)
Рохан

Ключовим для мене було використання setRawInputTypeзамістьsetInputType
Tamoxin

9

Я думаю, що це спосіб зробити те, що ти робиш. Маючи android:inputType="textMultiLine", 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 == KeyEvent.KEYCODE_ENTER){
                //do your stuff here
            }
            return false;
        }
});

Використовуючи фіксовану кількість максимальних чисел з андроїдом: рядки = "10" працювали для мене, отримуючи кнопку "ОК" на клавіатурі. Хороший трюк, якщо хтось знає, скільки буде рядків, наприклад, з невеликим набором maxLength.
сунадорер

Я хочу відключити keyCode № 66, чи можливо це? Як я можу це зробити?
Аділ Малик

1
чому keyCode == 66 замість keyCode == EditorInfo.IME_ACTION_GO?
це

5

Це, здається, працює на мене ідеально

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

4

Рішення Котліна, яке можна використовувати повторно

Встановлення цих значень у коді було єдиним, що працювало для мене

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

Я вимагаю цього часто, тому зробив це, щоб код був чистим:

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)

Якщо ви хочете додати необов’язкові спеціальні дії у "Готово", спробуйте:

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

Потрібно легко керувати клавіатурою під час зворотного дзвінка? Прочитайте цю публікацію

Потім додайте hideKeyboard()дзвінокEditText.multilineDone


1
☝️Це чудова відповідь
Майкл

3

Коротка відповідь: Ні, я вважаю, що це неможливо до рівня API 11 (3.0).

Тут обговорюється те саме питання (обговорюється в коментарях до прийнятої відповіді):

Кнопка дії Android Soft Клавіатура

З остаточного коментаря:

Дивлячись на кілька додатків на моєму телефоні, здається, що мультилінійне поле останнє, з ним видимі кнопки "Готово" або "Надіслати" (наприклад, програма електронної пошти).


3

Простий спосіб подолати цю ситуацію:

  • зберігати ці атрибути в 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;
         }
         }
    });

2

Якщо мова йде не про зовнішній вигляд екранної клавіатури, ви можете просто поставити слухач вводу на клавіатуру і запустити "зроблений" -статус, якщо користувач введе новий рядок.


2

якщо ви використовуєте параметр введення textImeMultiline з imeoptions flagnext і actionnext, ви отримаєте наступну кнопку замість повернення каретки


2

Хоча жодне з інших рішень для мене ніколи не працювало, наступне працювало прекрасно і врятували мені дні та дні більш гуглого, з декількома моїми звитками, звичайно. На жаль, не пам'ятаю, звідки я точно взяв код, і тому не можу дати авторові заслуги, яку він / вона так заслуговує.

У вашому коді 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;
        }
});




1

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

Найменше рішення, яке я виявив, що не передбачає переоформлення поведінки повернення перевезення, тут: https://stackoverflow.com/a/12570003/3268329 . Це рішення зведе нанівець невблаганне бажання Android примусити встановити прапор IME_FLAG_NO_ENTER_ACTION для перегляду в рядках, що призводить до зникнення кнопки Готово.


0

Я боровся також досить довго, але я нарешті знайшов рішення!

Просто створіть спеціальний клас 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 на NameAction;).

Вам потрібно просто викликати його у своєму XML замість класичного класу EditText.

Щоб пояснити логіку тут:

  • Встановіть EditText як єдиний рядок, щоб мати змогу відображати кнопку NameAction замість Enter.
  • Видаліть горизонтальну прокрутку, щоб текст перейшов до наступного рядка, доходячи до кінця перегляду.
  • Слідкуйте за змінами макета за допомогою onGlobalLayoutListener і встановіть параметр "рядок" на "рядок рядка" поточного тексту, що міститься у редакторі editText. Це те, що освіжає його висоту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.