Как мне обработать нажатие кнопки ImeOptions?

185

У меня есть, EditTextгде я устанавливаю следующее свойство, чтобы я мог отобразить кнопку Готово на клавиатуре, когда пользователь нажимает на EditText.

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

Когда пользователь нажимает кнопку «Готово» на экранной клавиатуре (ввод закончен), я хочу изменить RadioButtonсостояние.

Как я могу отследить готовую кнопку, когда она нажата с экранной клавиатуры?

Снимок экрана, показывающий нижнюю правую кнопку "Готово" на программной клавиатуре

D-Man
источник
1
Может быть, OnKeyboardActionListener поможет мне любой пример кода?
d-man

Ответы:

210

Я получил комбинацию ответов Робертса и Чирага:

((EditText)findViewById(R.id.search_field)).setOnEditorActionListener(
        new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        // Identifier of the action. This will be either the identifier you supplied,
        // or EditorInfo.IME_NULL if being called due to the enter key being pressed.
        if (actionId == EditorInfo.IME_ACTION_SEARCH
                || actionId == EditorInfo.IME_ACTION_DONE
                || event.getAction() == KeyEvent.ACTION_DOWN
                && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
            onSearchAction(v);
            return true;
        }
        // Return true if you have consumed the action, else false.
        return false;
    }
});

Обновление: приведенный выше код иногда активирует обратный вызов дважды. Вместо этого я выбрал следующий код, который я получил от клиентов чата Google:

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    // If triggered by an enter key, this is the event; otherwise, this is null.
    if (event != null) {
        // if shift key is down, then we want to insert the '\n' char in the TextView;
        // otherwise, the default action is to send the message.
        if (!event.isShiftPressed()) {
            if (isPreparedForSending()) {
                confirmSendMessageIfNeeded();
            }
            return true;
        }
        return false;
    }

    if (isPreparedForSending()) {
        confirmSendMessageIfNeeded();
    }
    return true;
}
Томас Але
источник
4
Я просто искал IME_ACTION_DONE и был удивлен, что это не сработало. После того, как я также искал ACTION_DOWN и KEYCODE_ENTER, он, наконец, активировал onEditorAction (). Поскольку я не вижу разницы во встроенной клавиатуре (я ожидал, что клавиша Enter будет выделена), мне интересно, в чем смысл использования android: imeOptions = "actionSend" для XML-макета EditText.
Кто-то где-то
почему этот ответ не принят. это терпит неудачу в нескольких случаях ??
Archie.bpgc
1
developer.android.com/reference/android/widget/… (описание того, что такое «событие», подтверждает то же самое.)
Дарпан
2
Второе решение также запускается дважды.
Bagusflyer
1
Что isPreparedForSending()и почему возвращает второй метод true?
CoolMind
122

Попробуйте это, это должно работать для того, что вам нужно:


editText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    if (actionId == EditorInfo.IME_ACTION_DONE) {
       //do here your stuff f
       return true;
    }
    return false;
    } 
});
chikka.anddev
источник
10
Это не работает для HTC Evo. Насколько я понял, HTC реализовала собственную программную клавиатуру, которая игнорирует imeOptions.
Дан
Этого достаточно (не нужно смотреть на действие события или код ключа, как в принятом ответе); работает на моих тестовых устройствах Nexus и Samsung.
Джоник
просто чтобы быть уверенным, убедитесь, что действие в коде и представлении совпадает <EditText android:imeOptions="actionDone" android:inputType="text"/>
bh_earth0
40
<EditText android:imeOptions="actionDone"
          android:inputType="text"/>

Java-код:

edittext.setOnEditorActionListener(new OnEditorActionListener() { 
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            Log.i(TAG,"Here you can write the code");
            return true;
        }    
        return false;
    }
});
Vinoj Vetha
источник
Вы должны вернуть true в предложении if, чтобы сказать, что вы справились с этим
Тим Кист
26

Я знаю, что этот вопрос старый, но я хочу указать, что сработало для меня.

Я попытался использовать пример кода с сайта разработчиков Android (показан ниже), но он не сработал. Поэтому я проверил класс EditorInfo и понял, что целочисленное значение IME_ACTION_SEND было указано как 0x00000004.

Пример кода от разработчиков Android:

editTextEmail = (EditText) findViewById(R.id.editTextEmail);
editTextEmail
        .setOnEditorActionListener(new OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId,
                    KeyEvent event) {
                boolean handled = false;
                if (actionId == EditorInfo.IME_ACTION_SEND) {
                    /* handle action here */
                    handled = true;
                }
                return handled;
            }
        });

Итак, я добавил целочисленное значение в мой res/values/integers.xmlфайл.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="send">0x00000004</integer>
</resources>

Затем я отредактировал свой файл макета res/layouts/activity_home.xmlследующим образом

<EditText android:id="@+id/editTextEmail"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:imeActionId="@integer/send"
  android:imeActionLabel="@+string/send_label"
  android:imeOptions="actionSend"
  android:inputType="textEmailAddress"/>

И тогда пример кода сработал.

iRuth
источник
17

Подробнее о том, как установить OnKeyListener и как он слушает кнопку Готово.

Сначала добавьте OnKeyListener в секцию инструментов вашего класса. Затем добавьте функцию, определенную в интерфейсе OnKeyListener:

/*
 * Respond to soft keyboard events, look for the DONE press on the password field.
 */
public boolean onKey(View v, int keyCode, KeyEvent event)
{
    if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
        (keyCode == KeyEvent.KEYCODE_ENTER))
    {
        // Done pressed!  Do something here.
    }
    // Returning false allows other listeners to react to the press.
    return false;
}

Учитывая объект EditText:

EditText textField = (EditText)findViewById(R.id.MyEditText);
textField.setOnKeyListener(this);
Роберт Хоки
источник
2
Это больше не работает в приложениях, ориентированных на уровень API 17+, поскольку ваш OnKeyListener больше не запускается для событий программных клавиш: developer.android.com/reference/android/text/method/…
jjb
Они предлагают альтернативу сейчас?
Роберт Хоки
2
Я переключился на использование setOnEditorActionListener для поиска EditorInfo.IME_ACTION_DONE, который, кажется, работает хорошо.
JJB
OnKey должен возвращать true, а не false.
ralphgabb
16

Хотя большинство людей ответили на вопрос напрямую, я хотел бы подробнее остановиться на концепции, стоящей за этим. Во-первых, я привлек внимание IME, когда создавал активность по умолчанию для входа. Это сгенерировало некоторый код для меня, который включал следующее:

<EditText
  android:id="@+id/password"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:hint="@string/prompt_password"
  android:imeActionId="@+id/login"
  android:imeActionLabel="@string/action_sign_in_short"
  android:imeOptions="actionUnspecified"
  android:inputType="textPassword"
  android:maxLines="1"
  android:singleLine="true"/>

Вы уже должны быть знакомы с атрибутом inputType. Это просто сообщает Android тип ожидаемого текста, например адрес электронной почты, пароль или номер телефона. Полный список возможных значений можно найти здесь .

Это был, однако, признак того, imeOptions="actionUnspecified"что я не понимал его цели. Android позволяет вам взаимодействовать с клавиатурой, которая появляется в нижней части экрана при выделении текста с помощьюInputMethodManager . В нижнем углу клавиатуры есть кнопка, обычно она говорит «Далее» или «Готово», в зависимости от текущего текстового поля. Android позволяет настроить это с помощью android:imeOptions. Вы можете указать кнопку «Отправить» или «Далее». Полный список можно найти здесь .

При этом, вы можете слушать нажатия на кнопку действия, задав условие TextView.OnEditorActionListenerдляEditText элемента. Как в вашем примере:

editText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(EditText v, int actionId, KeyEvent event) {
    if (actionId == EditorInfo.IME_ACTION_DONE) {
       //do here your stuff f
       return true;
    }
    return false;
    } 
});

Теперь в моем примере у меня был android:imeOptions="actionUnspecified"атрибут. Это полезно, когда вы хотите попытаться войти в систему, когда пользователь нажимает клавишу ввода. В своей деятельности вы можете обнаружить этот тег, а затем попытаться войти в систему:

    mPasswordView = (EditText) findViewById(R.id.password);
    mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
            if (id == R.id.login || id == EditorInfo.IME_NULL) {
                attemptLogin();
                return true;
            }
            return false;
        }
    });
Донато
источник
6

Благодаря chikka.anddev и Alex Cohn в Котлине это:

text.setOnEditorActionListener { v, actionId, event ->
    if (actionId == EditorInfo.IME_ACTION_DONE ||
        event?.action == KeyEvent.ACTION_DOWN && event.keyCode == KeyEvent.KEYCODE_ENTER) {
        doSomething()
        true
    } else {
        false
    }
}

Здесь я проверяю Enterключ, потому что он возвращает EditorInfo.IME_NULLвместо IME_ACTION_DONE.

См. Также Android imeOptions = "actionDone" не работает . Добавьте android:singleLine="true"в EditText.

CoolMind
источник
6

Kotlin Solution

Базовый способ справиться с этим в Котлине:

edittext.setOnEditorActionListener { _, actionId, _ ->
    if (actionId == EditorInfo.IME_ACTION_DONE) {
        callback.invoke()
        true
    }
    false
}

Удлинение Котлина

Используйте это, чтобы просто позвонить edittext.onDone{/*action*/}в ваш основной код. Делает ваш код более читабельным и понятным

fun EditText.onDone(callback: () -> Unit) {
    setOnEditorActionListener { _, actionId, _ ->
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            callback.invoke()
            true
        }
        false
    }
}

Не забудьте добавить эти опции в ваш текст редактирования

<EditText ...
    android:imeOptions="actionDone"
    android:inputType="text"/>

Если вам нужна inputType="textMultiLine"поддержка, прочитайте этот пост

Gibolt
источник
1
Отличный ответ, спасибо, что поделились! Я, кажется, продолжаю получать предупреждение Lint относительно возвращаемого значения setOnEditorActionListener, хотя. Возможно, это просто вопрос локальных настроек конфигурации, но мой линтер действительно очень хочет , чтобы я elseтоже добавил ветку, чтобы принять "true" в качестве оператора возврата слушателя (в отличие от if-block).
дБмВт
0

Если вы используете аннотации Android https://github.com/androidannotations/androidannotations

Вы можете использовать аннотацию @EditorAction

@EditorAction(R.id.your_component_id)
void onDoneAction(EditText view, int actionId){
    if(actionId == EditorInfo.IME_ACTION_DONE){
        //Todo: Do your work or call a method
    }
}
Рафаэль Роча
источник