240 votes

Comment gérer le clic sur le bouton "done" de ImeOptions ?

J'ai un EditText où je définis la propriété suivante afin de pouvoir afficher le bouton "done" sur le clavier lorsque l'utilisateur clique sur l'EditText.

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

Lorsque l'utilisateur clique sur le bouton "Terminé" du clavier de l'écran (lorsqu'il a fini de taper), je veux modifier un paramètre de l'écran. RadioButton l'État.

Comment puis-je suivre le bouton fait quand il est frappé à partir du clavier de l'écran ?

Screenshot showing the bottom right 'done' button on the software keyboard

1 votes

Peut-être que OnKeyboardActionListener m'aidera à trouver un exemple de code ?

235voto

Thomas Ahle Points 10403

Je me suis retrouvé avec une combinaison de réponses de Roberts et de Chirags :

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

Mise à jour : Le code ci-dessus pourrait parfois activer deux fois le rappel. Au lieu de cela, j'ai opté pour le code suivant, que j'ai obtenu à partir des clients de chat de 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;
}

5 votes

Je viens de chercher IME_ACTION_DONE et j'ai été surpris qu'il ne se déclenche pas. Après avoir également recherché ACTION_DOWN et KEYCODE_ENTER, j'ai finalement déclenché onEditorAction(). Comme je ne vois aucune différence avec le clavier intégré (je m'attendais à ce que la touche Entrée soit mise en évidence), je me demande quel est l'intérêt d'utiliser Android:imeOptions="actionSend" pour la disposition XML EditText.

0 votes

Pourquoi cette réponse n'est pas acceptée. est-ce que cela échoue dans quelques cas ?

0 votes

Mais cela ne peut pas fonctionner comme un TextView multi-ligne, Dans ce cas, vous ne pouvez pas créer le TextView multi-ligne en utilisant le chat

142voto

chirag shah Points 4188

Essayez ceci, cela devrait correspondre à ce dont vous avez besoin :


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

11 votes

Cela ne fonctionne pas pour le HTC Evo. D'après ce que j'ai pu comprendre, HTC a implémenté son propre clavier souple qui ignore les imeOptions.

0 votes

Cela suffit (pas besoin de regarder l'action de l'événement ou le code de la clé, comme dans la réponse acceptée) ; cela fonctionne sur mes appareils de test Nexus et Samsung.

2 votes

Juste pour être sûr, assurez-vous que l'action dans le code et la vue correspondent <EditText android:imeOptions="actionDone" android:inputType="text"/>

55voto

Gibolt Points 4072

Solution Kotlin

La méthode de base pour le gérer en Kotlin est la suivante :

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

Extension Kotlin

Utilisez ceci pour appeler simplement edittext.onDone{/*action*/} dans votre code principal. Rend votre code beaucoup plus lisible et facile à maintenir.

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

N'oubliez pas d'ajouter ces options à votre texte d'édition.

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

Si vous avez besoin inputType="textMultiLine" soutien, lire cet article

2 votes

Excellente réponse, merci de la partager ! Il semble que je continue à recevoir un avertissement de lint concernant la valeur de retour de la fonction setOnEditorActionListener Mais Peut-être que c'est juste une question de paramètres de configuration locale, mais mon linter vraiment, vraiment veut que j'ajoute un else afin d'accepter la valeur "true" comme déclaration de retour de l'écouteur (par opposition à la fonction if -bloc).

1 votes

Vous avez besoin de la else sinon il retournera toujours false . Un lambda est une expression, le résultat est toujours la dernière valeur exprimée. Même si vous passez par le if branche et express true vous passez immédiatement à la ligne suivante et vous exprimez false - donc c'est toujours votre résultat ! Avoir un if-else comme dernière instruction signifie que vous descendez dans une branche ou l'autre, et c'est la dernière chose que vous faites dans le lambda, donc vous retournez le résultat de cette branche.

3 votes

Vous avez une erreur pour le lambda. Au lieu de true vous devez écrire return@setOnEditorActionListener true sinon, il passera à false dans tous les cas.

53voto

Vinoj Vetha Points 338
<EditText android:imeOptions="actionDone"
          android:inputType="text"/>

Le code Java est :

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

0 votes

Vous devriez renvoyer true dans la clause if pour dire que vous l'avez traité.

27voto

iRuth Points 2419

Je sais que cette question est ancienne, mais je tiens à souligner ce qui a fonctionné pour moi.

J'ai essayé d'utiliser l'exemple de code de la Site web des développeurs Android (montré ci-dessous), mais ça n'a pas marché. J'ai donc vérifié la classe EditorInfo, et j'ai réalisé que la valeur entière IME_ACTION_SEND était spécifiée en tant que 0x00000004 .

Exemple de code provenant de développeurs 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;
            }
        });

Donc, j'ai ajouté la valeur entière à mon res/values/integers.xml fichier.

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

Ensuite, j'ai modifié mon fichier de mise en page res/layouts/activity_home.xml comme suit

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

Et puis, l'exemple de code a fonctionné.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X