Come gestisco il clic sul pulsante Fine di ImeOptions?


185

Sto avendo un punto in EditTextcui sto impostando la seguente proprietà in modo da poter visualizzare il pulsante Fine sulla tastiera quando l'utente fa clic su EditText.

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

Quando l'utente fa clic sul pulsante Fine sulla tastiera dello schermo (terminata la digitazione), voglio cambiare uno RadioButtonstato.

Come posso tenere traccia del pulsante Fine quando viene colpito dalla tastiera dello schermo?

Schermata che mostra il pulsante 'fatto' in basso a destra sulla tastiera del software


1
può essere OnKeyboardActionListener aiutarmi con qualsiasi esempio di codice ??
d-man il

Risposte:


210

Ho finito con una combinazione di Roberts e risposte chirag:

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

Aggiornamento: alcune volte il codice sopra potrebbe attivare due volte il callback. Invece ho optato per il seguente codice, che ho ottenuto dai client di chat di 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
Ho appena cercato IME_ACTION_DONE e sono rimasto sorpreso dal fatto che non si sia attivato. Dopo aver cercato anche ACTION_DOWN e KEYCODE_ENTER, alla fine si è attivato suEditorAction (). Dal momento che non vedo alcuna differenza nella tastiera integrata (mi aspettavo che il tasto Invio fosse evidenziato) Mi chiedo quale sia lo scopo dell'utilizzo di Android: imeOptions = "actionSend" per il layout XML EditText.
Qualcuno da qualche parte

perché questa risposta non è accettata? questo fallisce in alcuni casi ??
Archie.bpgc,

1
developer.android.com/reference/android/widget/… (Descrizione di ciò che un "evento" è lo stesso).
Darpan,

2
Anche la seconda soluzione viene attivata due volte.
Bagusflyer,

1
Che cos'è isPreparedForSending()e perché ritorna il secondo metodo true?
CoolMind

122

Prova questo, dovrebbe funzionare per quello che ti serve:


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
Questo non funziona per HTC Evo. Per quanto ho potuto capire, HTC ha implementato la propria tastiera software che ignora le imeOpzioni.
Dan,

Questo è sufficiente (non è necessario guardare l'azione dell'evento o il codice chiave, come nella risposta accettata); funziona sui miei dispositivi di test Nexus e Samsung.
Jonik,

solo per sicurezza, assicurati che l'azione nel codice e la vista corrispondano <EditText android:imeOptions="actionDone" android:inputType="text"/>
bh_earth0

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

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

Dovresti tornare vero nella clausola if per dire che l'hai gestita
Tim Kist,

26

So che questa domanda è vecchia, ma voglio sottolineare cosa ha funzionato per me.

Ho provato a utilizzare il codice di esempio dal sito Web degli sviluppatori Android (mostrato di seguito), ma non ha funzionato. Quindi ho controllato la classe EditorInfo e mi sono reso conto che il valore intero IME_ACTION_SEND è stato specificato come 0x00000004.

Codice di esempio dagli sviluppatori 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;
            }
        });

Quindi, ho aggiunto il valore intero al mio res/values/integers.xmlfile.

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

Quindi, ho modificato il mio file di layout res/layouts/activity_home.xmlcome segue

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

E poi, il codice di esempio ha funzionato.


17

Maggiori dettagli su come impostare OnKeyListener e fare in modo che ascolti il ​​pulsante Fine.

Per prima cosa aggiungi OnKeyListener alla sezione attrezzi della tua classe. Quindi aggiungere la funzione definita nell'interfaccia 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;
}

Dato un oggetto EditText:

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

2
Questo non funziona più sulle applicazioni destinate al livello API 17+, perché il tuo OnKeyListener non viene più attivato per eventi soft-key: developer.android.com/reference/android/text/method/…
jjb

Suggeriscono un'alternativa adesso?
Robert Hawkey,

2
Sono passato a usare setOnEditorActionListener per cercare EditorInfo.IME_ACTION_DONE, che sembra funzionare bene.
jjb,

onKey dovrebbe restituire true, non false.
ralphgabb,

16

Mentre la maggior parte delle persone ha risposto direttamente alla domanda, volevo approfondire il concetto alla base. Innanzitutto, sono stato attratto dall'IME quando ho creato un'attività di accesso predefinita. Ha generato un codice per me che includeva quanto segue:

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

Dovresti già avere familiarità con l'attributo inputType. Questo informa solo Android del tipo di testo previsto, come un indirizzo e-mail, una password o un numero di telefono. L'elenco completo dei possibili valori è disponibile qui .

Era, tuttavia, l'attributo imeOptions="actionUnspecified"che non ho capito il suo scopo. Android ti consente di interagire con la tastiera che si apre dalla parte inferiore dello schermo quando il testo è selezionato usando il InputMethodManager. Nell'angolo in basso della tastiera, c'è un pulsante, in genere dice "Avanti" o "Fatto", a seconda del campo di testo corrente. Android ti consente di personalizzare questo usando android:imeOptions. È possibile specificare un pulsante "Invia" o "Avanti". L'elenco completo è disponibile qui .

Con ciò, puoi quindi ascoltare le pressioni sul pulsante di azione definendo a TextView.OnEditorActionListenerper l' EditTextelemento. Come nel tuo esempio:

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

Ora nel mio esempio avevo un android:imeOptions="actionUnspecified"attributo. Ciò è utile quando si desidera provare ad accedere a un utente quando premono il tasto Invio. Nella tua attività, puoi rilevare questo tag e quindi tentare l'accesso:

    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

Grazie a chikka.anddev e Alex Cohn a Kotlin è:

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

Qui cerco Enterchiave, perché restituisce EditorInfo.IME_NULLinvece di IME_ACTION_DONE.

Vedi anche Android imeOptions = "actionDone" non funziona . Aggiungi android:singleLine="true"in EditText.


6

Soluzione di Kotlin

Il modo di base per gestirlo in Kotlin è:

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

Estensione di Kotlin

Usa questo per chiamare semplicemente il edittext.onDone{/*action*/}tuo codice principale. Rende il tuo codice molto più leggibile e gestibile

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

Non dimenticare di aggiungere queste opzioni al tuo edittext

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

Se hai bisogno di inputType="textMultiLine"supporto, leggi questo post


1
Ottima risposta, grazie per la condivisione! Sembra che continui a ricevere un avviso di lanugine riguardo al valore di ritorno di setOnEditorActionListener, comunque. Forse è solo una questione di impostazioni di configurazione locali, ma la mia linter vuole davvero che io aggiunga anche un elseramo per accettare il "vero" come una dichiarazione di ritorno dell'ascoltatore (al contrario del ifblocco).
dbm

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.