Jak poradzić sobie z wykonanym kliknięciem przycisku ImeOptions?


185

Mam miejsce, w EditTextktórym ustawiam następującą właściwość, dzięki czemu mogę wyświetlić przycisk Gotowe na klawiaturze, gdy użytkownik kliknie EditText.

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

Kiedy użytkownik kliknie przycisk Gotowe na klawiaturze ekranowej (kończy pisanie), chcę zmienić RadioButtonstan.

Jak mogę śledzić zrobiony przycisk po naciśnięciu go z klawiatury ekranowej?

Zrzut ekranu przedstawiający prawy dolny przycisk „gotowe” na klawiaturze oprogramowania


1
może być OnKeyboardActionListener pomóc mi dowolny przykład kodu?
d-man

Odpowiedzi:


210

Skończyło się na kombinacji odpowiedzi Robertsa i chiraga:

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

Aktualizacja: powyższy kod czasami aktywuje oddzwanianie dwukrotnie. Zamiast tego wybrałem następujący kod, który otrzymałem od klientów czatu 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
Właśnie szukałem IME_ACTION_DONE i byłem zaskoczony, że się nie uruchomił. Po tym, jak szukałem również ACTION_DOWN i KEYCODE_ENTER, w końcu zadziałało onEditorAction (). Ponieważ nie widzę żadnej różnicy we wbudowanej klawiaturze (spodziewałem się podświetlenia klawisza Enter), zastanawiam się, o co chodzi z używaniem Androida: imeOptions = "actionSend" dla układu XML EditText.
Ktoś gdzieś

dlaczego ta odpowiedź nie jest akceptowana. czy to się nie powiedzie w kilku przypadkach?
Archie.bpgc

1
developer.android.com/reference/android/widget/… (Opis tego, co „wydarzenie” jest takie samo.)
Darpan

2
Drugie rozwiązanie jest również uruchamiane dwukrotnie.
Bagusflyer

1
Co to jest isPreparedForSending()i dlaczego powraca druga metoda true?
CoolMind

122

Wypróbuj to, powinno działać dla tego, czego potrzebujesz:


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
To nie działa dla HTC Evo. O ile mogłem zrozumieć, HTC zaimplementowało własną miękką klawiaturę, która ignoruje imeOptions.
Dan

To wystarczy (nie trzeba patrzeć na akcję zdarzenia lub kod klucza, jak w zaakceptowanej odpowiedzi); działa na moich urządzeniach testowych Nexus i Samsung.
Jonik,

dla bezpieczeństwa, upewnij się, że działanie w kodzie i widoku pasuje <EditText android:imeOptions="actionDone" android:inputType="text"/>
bh_earth0

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

Kod Java to:

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

Powinieneś zwrócić prawdę w klauzuli if, aby powiedzieć, że sobie z tym poradziłeś
Tim Kist,

26

Wiem, że to pytanie jest stare, ale chcę wskazać, co dla mnie zadziałało.

Próbowałem użyć przykładowego kodu ze strony Android Developers (pokazanej poniżej), ale to nie działało. Sprawdziłem więc klasę EditorInfo i zdałem sobie sprawę, że wartość całkowitą IME_ACTION_SEND podano jako 0x00000004.

Przykładowy kod od programistów Androida:

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

Więc dodałem wartość całkowitą do mojego res/values/integers.xmlpliku.

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

Następnie zmodyfikowałem plik układu res/layouts/activity_home.xmlw następujący sposób

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

A potem zadziałał przykładowy kod.


17

Więcej informacji na temat ustawiania OnKeyListener i słuchanie przycisku Gotowe.

Najpierw dodaj OnKeyListener do sekcji implementacji swojej klasy. Następnie dodaj funkcję zdefiniowaną w interfejsie 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;
}

Biorąc pod uwagę obiekt EditText:

EditText textField = (EditText)findViewById(R.id.MyEditText);
textField.setOnKeyListener(this);

2
To już nie działa w aplikacjach ukierunkowanych na API w wersji 17+, ponieważ Twój OnKeyListener nie jest już uruchamiany w przypadku zdarzeń klawiszowych: developer.android.com/reference/android/text/method/…
jjb

Czy sugerują teraz alternatywę?
Robert Hawkey

2
Przełączyłem się na używanie setOnEditorActionListener w celu szukania EditorInfo.IME_ACTION_DONE, który wydaje się działać dobrze.
jjb

onKey powinien zwracać wartość true, a nie false.
ralphgabb

16

Podczas gdy większość ludzi odpowiedziała bezpośrednio na to pytanie, chciałem bardziej szczegółowo rozwinąć koncepcję tego pytania. Po pierwsze, zwróciłem uwagę IME, kiedy utworzyłem domyślną aktywność logowania. Wygenerował dla mnie trochę kodu, który obejmował:

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

Powinieneś już być zaznajomiony z atrybutem inputType. To tylko informuje Androida o oczekiwanym typie tekstu, takim jak adres e-mail, hasło lub numer telefonu. Pełna lista możliwych wartości znajduje się tutaj .

Był to jednak atrybut imeOptions="actionUnspecified", że nie rozumiałem jego celu. Android pozwala na interakcję z klawiaturą, która wyskakuje z dołu ekranu, gdy tekst jest zaznaczany za pomocą InputMethodManager. W dolnym rogu klawiatury znajduje się przycisk, zwykle z napisem „Dalej” lub „Gotowe”, w zależności od bieżącego pola tekstowego. Android pozwala to dostosować za pomocą android:imeOptions. Możesz określić przycisk „Wyślij” lub „Dalej”. Pełna lista znajduje się tutaj .

Dzięki temu możesz nasłuchiwać nacisków na przycisku akcji, definiując element TextView.OnEditorActionListenerdla EditTextelementu. Jak w twoim przykładzie:

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

Teraz w moim przykładzie miałem android:imeOptions="actionUnspecified"atrybut. Jest to przydatne, gdy chcesz spróbować zalogować się do użytkownika po naciśnięciu klawisza Enter. W swojej aktywności możesz wykryć ten tag, a następnie spróbować zalogować się:

    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

Dzięki chikka.anddev i Alexowi Cohnowi w Kotlinie jest to:

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

Tutaj sprawdzam Enterklucz, ponieważ zwraca EditorInfo.IME_NULLzamiast IME_ACTION_DONE.

Zobacz także Android imeOptions = „actionDone” nie działa . Dodaj android:singleLine="true"w EditText.


6

Rozwiązanie Kotlin

Podstawowym sposobem obsługi tego w Kotlin jest:

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

Rozszerzenie Kotlin

Użyj tego, aby po prostu wywołać edittext.onDone{/*action*/}swój główny kod. Sprawia, że ​​Twój kod jest znacznie bardziej czytelny i łatwy w konserwacji

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

Nie zapomnij dodać tych opcji do tekstu edycji

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

Jeśli potrzebujesz inputType="textMultiLine"wsparcia, przeczytaj ten post


1
Świetna odpowiedź, dziękuję za udostępnienie! Wydaje mi się jednak, że wciąż otrzymuję ostrzeżenie o zwracanej wartości setOnEditorActionListener. Może to tylko kwestia lokalnych ustawień konfiguracyjnych, ale mój linter naprawdę, naprawdę chce mnie dodać elsegałąź też, aby zaakceptować „true” w instrukcji return słuchacza (w przeciwieństwie do if-blok).
dbm

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.