Як обробити натиснуту кнопку кнопки ІмеОпції?


185

У мене є місце, EditTextде я встановлюю таке властивість, щоб я міг відображати виконану кнопку на клавіатурі, коли користувач натискає на EditText.

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

Коли користувач натискає кнопку "Готово" на екранній клавіатурі (закінчив вводити), я хочу змінити RadioButtonстан.

Як я можу відстежувати виконану кнопку, коли вона натискається з клавіатури екрана?

Знімок екрана, що показує нижню праву кнопку "зроблено" на клавіатурі програмного забезпечення


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

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

Вам слід повернути істину в пункті 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"/>

А потім, зразок коду працював.


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 повинен повернути справжнє, а не хибне.
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 та Алекс Кон в Котліні :

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.


6

Рішення Котліна

Основний спосіб поводження з ним у Котліні:

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

Розширення Kotlin

Використовуйте це, щоб просто зателефонувати 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"підтримка, прочитайте цю публікацію


1
Чудова відповідь, дякую за обмін! Я, здається, продовжую отримувати попередження про вказівку щодо поверненої вартості setOnEditorActionListener, хоча. Може бути , це просто питання локальних налаштувань конфігурації, але мій Лінтера дійсно, на самому ділі хоче , щоб я додати elseгілку теж для того , щоб прийняти «істинний» в якості оператора повернення слухача (на відміну від if-блока).
dbm

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