Многострочный EditText с меткой Done SoftInput в версии 2.3

82

Есть ли способ иметь многострочность EditTextи использовать метку действия IME «Готово» на Android 2.3?

В Android 2.2 это не проблема, кнопка ввода показывает метку действия IME «Готово» ( android:imeActionLabel="actionDone") и закрывает мягкий ввод при нажатии.

При настройке EditTextдля многострочного режима Android 2.3 удаляет возможность отображать действие «Готово» для клавиатуры мягкого ввода.

Мне удалось изменить поведение кнопки ввода мягкого ввода с помощью a KeyListener, однако кнопка ввода по-прежнему выглядит как клавиша ввода.


Вот декларация EditText

<EditText
        android:id="@+id/Comment"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="0dp"
        android:lines="3"
        android:maxLines="3"
        android:minLines="3"
        android:maxLength="60"
        android:scrollHorizontally="false"
        android:hint="hint"
        android:gravity="top|left"
        android:textColor="#888"
        android:textSize="14dp"
        />
<!-- android:inputType="text" will kill the multiline on 2.3! -->
<!-- android:imeOptions="actionDone" switches to a "t9" like soft input -->

Когда я проверяю inputTypeзначение после загрузки настройки представления содержимого в действии, оно отображается как:

inputType = 0x20001

Который:

  • class = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_NORMAL
  • флаги = InputType.TYPE_TEXT_FLAG_MULTI_LINE
охороб
источник

Ответы:

163

Ну, а после повторного прочтения TextViewи EditorInfoдокументов, стало ясно , что платформа будет силы IME_FLAG_NO_ENTER_ACTIONдля представлений многострочного текста.

Обратите внимание, что TextViewэтот флаг автоматически установится для вас при просмотре многострочного текста.

Мое решение - создать подкласс EditTextи настроить параметры IME после того, как платформа настроит их:

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    InputConnection connection = super.onCreateInputConnection(outAttrs);
    int imeActions = outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION;
    if ((imeActions&EditorInfo.IME_ACTION_DONE) != 0) {
        // clear the existing action
        outAttrs.imeOptions ^= imeActions;
        // set the DONE action
        outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
    }
    if ((outAttrs.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
        outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
    }
    return connection;
}

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

охороб
источник
24
Обычно я не даю общих комментариев, таких как «боже, спасибо», но этот ответ был достаточно полезным и недооцененным, и я подумал, что он заслуживает признания. В общем, спасибо. :-)
пахарь
3
+1 за ответ, но если в этом случае вы устанавливаете тип ввода текста редактирования из кода. Он убирает вертикальную прокрутку и добавляет горизонтальную прокрутку. Чтобы решить эту проблему, используйте приведенный ниже код. editTextObj.setInputType (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE); Обычно это может произойти, если вы повторно используете представление, включая его в несколько макетов. @ohhorob большое спасибо за решение.
Jayshil Dave 02
2
Отлично работает! Но я не очень понимаю код. У вас есть место, где я могу прочитать обо всем механизме флагов?
vanleeuwenbram
Спасибо, я новичок, я поместил это в свое действие, которое использует диалоговое окно EditText, поэтому его нет в моем действии xml. Я пытался поставить этот код в моей деятельности, но получил сообщение об ошибке: The method onCreateInputConnection(EditorInfo) of type SMSMain must override or implement a supertype method. Вы звоните superв начале, поэтому не знаете, в чем проблема. Есть предложения? Благодарю.
Azurespot 01
@NoniA. вам нужно создать подкласс EditText. и в этом классе вы должны вызвать этот метод. создать класс, который расширяется до EditText. и поместите этот метод в этот класс.
Shah
104

Ответ Охороба в основном правильный, но его код действительно избыточен! Это в основном эквивалентно этой гораздо более простой версии (полный код для ленивых читателей):

package com.example.views;

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

// An EditText that lets you use actions ("Done", "Go", etc.) on multi-line edits.
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;
    }
}

Обратите внимание, что некоторые inputTypeпараметры, например, textShortMessageне работают! Предлагаю начать с inputType="text". Вот как вы можете использовать его в своем XML.

<com.example.views.ActionEditText
    android:id=...
    android:layout_stuff=...
    android:imeOptions="actionDone"
    android:inputType="textAutoCorrect|textCapSentences|textMultiLine"
    android:maxLines="3" />
Тимммм
источник
Тимммм, это проверено на 2.3?
ohhorob
1
Если ваш код работает на 2.3, мой тоже. Они почти одинаковы, и я основал свой или ваш код, так что спасибо! Есть ли в версии 2.3 идиосинкразии, которых нет в версии 4.0? Стандартное правило «никаких действий при многострочном редактировании» - это намеренное поведение, добавленное Google.
Timmmm
5
Я пробовал это на 2.3 (и 4.x), и это сработало для моего приложения.
mlc 08
2
@ matej.smitala Да, у вас не может быть и того, и другого.
Timmmm
1
После нескольких часов поиска лучшего решения это кажется лучшим и самым простым способом получения многострочного текста редактирования без клавиши ввода.
micnguyen
56

Альтернативным решением для создания подкласса класса EditText является настройка вашего экземпляра EditText следующим образом:

editText.setHorizontallyScrolling(false);
editText.setMaxLines(Integer.MAX_VALUE);

По крайней мере, у меня это работает на Android 4.0. Он настраивает экземпляр EditText так, чтобы пользователь редактировал однострочную строку, которая отображается с мягкой оболочкой на нескольких строках, даже если установлено действие IME.

Фуцилогик
источник
2
@Futzilogik: Вы, сэр, заслуживаете гораздо больше голосов! Этот ответ был очень простым и спасительным. Я имею в виду, вау. Хотел бы я проголосовать больше одного раза. Большое спасибо!
Swayam
3
Я использую 4.4.2, и это не сработало для меня или, по крайней мере, для моего способа сделать это. Я сделал это только в XML, так что, возможно, это проблема. Я настроил inputType на «textEmailAddress | textMultiLine», scrollHorizontally на false, maxLines на 500 (файл xml), singleLine на false и imeOptions на actionNext. Я попытался удалить "textMultiLine" из inputtype. С textMultiLine я получаю клавишу ENTER на клавиатуре, а без нее все остается на одной строке и по-прежнему прокручивается по горизонтали. Это действительно казалось самым простым решением, но то, что было выше, у меня работает, так что пока я им воспользуюсь.
реактивное ядро
6
Что касается моего предыдущего комментария (не удалось его отредактировать), подозревая, что это либо проблема с отсутствием установки MAX_VALUE, либо просто с изменением их после создания редактируемого текста, я попробовал использовать код, как указано здесь, и он работает! Я просто хотел опубликовать для других, вы не можете сделать это в XML (или я все равно не мог). У меня есть другие настройки: singleLine = false, imeOptions = actionNext, inputType = textEmailAddress (без многострочного).
реактивное ядро
работает очень хорошо. Это хороший пример улучшения старого ответа !!
nPn
Работаю для меня на Galaxy S5 с Lollipop. Отличное решение. Странно, что установка горизонтальной прокрутки в xml не имеет такого же эффекта,
Скотт Биркстед
7

После предыдущего ответа

public class MultiLineText extends EditText {

    public MultiLineText(Context context) {
        super(context);
    }

    public MultiLineText(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

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

    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        InputConnection connection = super.onCreateInputConnection(outAttrs);
        int imeActions = outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION;
        if ((imeActions&EditorInfo.IME_ACTION_DONE) != 0) {
            // clear the existing action
            outAttrs.imeOptions ^= imeActions;
            // set the DONE action
            outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
        }
        if ((outAttrs.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
            outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
        }
        return connection;
    }
}

Используйте это как

<myapp.commun.MultiLineText
  android:id="@+id/textNotes"
  android:layout_height="wrap_content"
  android:minHeight="100dp"
  android:layout_width="wrap_content"
  android:hint="Notes"
  android:textSize="20sp"
  android:padding="7dp"
  android:maxLines="4"/> 
пользователь3525689
источник
5

для выполнения действия Done вы можете использовать:

XML

android:inputType="text|textCapSentences"    

ЯВА

editText.setHorizontallyScrolling(false);
editText.setMaxLines(Integer.MAX_VALUE);

Надеюсь, это сработает для вас.

Алекс Зараос
источник
1

По-видимому, ответ на исходный вопрос - Да, но я считаю, что команда Android пытается заставить разработчиков немного подумать о том, как они используют многострочный EditText. Они хотят, чтобы клавиша ввода добавляла новые строки, и, вероятно, ожидают, что вы предоставите кнопку или другое средство ввода, чтобы вызвать событие, редактирование которого вы закончили.

У меня такая же проблема, и моим очевидным решением было просто добавить кнопку «Готово» и позволить кнопке ввода добавить новые строки.

Маллинз
источник
Извините, я, возможно, недостаточно ясно выразился в своем вопросе ... несколько строк предназначены для мягкого обертывания однострочного ввода. т.е. символы новой строки не допускаются.
ohhorob
@Mullins: Вы добавили собственную кнопку «Готово» на клавиатуру SoftInput? Как вы это сделали, не отпуская «Enter»?
alex.veprik 07
Нет. Я создал кнопку «Готово» в пользовательском интерфейсе отдельно от клавиатуры.
Mullins
1
Что ж, возможно, команда Android должна последовать своему собственному совету и заставить кнопку действия многострочного TextEdit в приложении для обмена сообщениями создавать новые строки вместо отправки сообщения.
Timmmm
0

Используйте этот атрибут в своем XML.

android: inputType = "textImeMultiLine"

android: imeOptions = "actionDone"

Гаурав
источник