Comment gérer le clic sur le bouton terminé d'ImeOptions?

185

Je suis en train de EditTextdéfinir la propriété suivante pour que je puisse afficher le bouton Terminé sur le clavier lorsque l'utilisateur clique sur EditText.

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

Lorsque l'utilisateur clique sur le bouton Terminé sur le clavier de l'écran (fini de taper), je souhaite modifier un RadioButtonétat.

Comment puis-je suivre le bouton Terminé lorsqu'il est frappé à partir du clavier à l'écran?

Capture d'écran montrant le bouton `` Terminé '' en bas à droite du clavier logiciel

d-man
la source
1
peut être OnKeyboardActionListener m'aider n'importe quel exemple de code ??
d-man

Réponses:

210

J'ai fini 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 activait parfois le rappel deux fois. Au lieu de cela, j'ai opté pour le code suivant, que j'ai obtenu des clients de chat 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;
}
Thomas Ahle
la source
4
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, il a finalement déclenché onEditorAction (). Comme je ne vois aucune différence dans 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 mise en page XML EditText.
Someone Somewhere
pourquoi cette réponse n'est-elle pas acceptée? cela échoue-t-il dans quelques cas ??
Archie.bpgc
1
developer.android.com/reference/android/widget/… (La description de ce qu'est un «événement» confirme la même chose.)
Darpan
2
La deuxième solution est également déclenchée deux fois.
Bagusflyer
1
Qu'est-ce que isPreparedForSending()et pourquoi la deuxième méthode retourne true?
CoolMind
122

Essayez ceci, cela devrait fonctionner pour 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;
    } 
});
chikka.anddev
la source
10
Cela ne fonctionne pas pour HTC Evo. Pour autant que j'ai pu comprendre, HTC a implémenté son propre clavier logiciel qui ignore les imeOptions.
Dan
Cela suffit (pas besoin de regarder l'action d'événement ou le code clé, comme dans la réponse acceptée); fonctionne sur mes appareils de test Nexus et Samsung.
Jonik
juste pour être sûr, assurez-vous que l'action dans le code et la vue correspond à <EditText android:imeOptions="actionDone" android:inputType="text"/>
bh_earth0
40
<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;
    }
});
Vinoj Vetha
la source
Vous devriez retourner true dans la clause if pour dire que vous l'avez géré
Tim Kist
26

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 du site Web des développeurs Android (illustré ci-dessous), mais cela n'a pas fonctionné. 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 comme 0x00000004.

Exemple de code des 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.xmlfichier.

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

Ensuite, j'ai édité mon fichier de mise en page res/layouts/activity_home.xmlcomme 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é.

iRuth
la source
17

Plus de détails sur la façon de définir OnKeyListener et de lui faire écouter le bouton Terminé.

Ajoutez d'abord OnKeyListener à la section implements de votre classe. Ajoutez ensuite la fonction définie dans l'interface 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;
}

Étant donné un objet EditText:

EditText textField = (EditText)findViewById(R.id.MyEditText);
textField.setOnKeyListener(this);
Robert Hawkey
la source
2
Cela ne fonctionne plus sur les applications ciblant le niveau d'API 17+, car votre OnKeyListener n'est plus déclenché pour les événements de touches programmables: developer.android.com/reference/android/text/method/…
jjb
Proposent-ils une alternative maintenant?
Robert Hawkey
2
Je suis passé à l'utilisation de setOnEditorActionListener pour rechercher EditorInfo.IME_ACTION_DONE, qui semble bien fonctionner.
jjb
onKey doit renvoyer true et non false.
ralphgabb
16

Alors que la plupart des gens ont répondu directement à la question, je voulais en dire plus sur le concept sous-jacent. Tout d'abord, j'ai été attiré l'attention de l'IME lorsque j'ai créé une activité de connexion par défaut. Il a généré du code pour moi qui comprenait ce qui suit:

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

Vous devez déjà être familiarisé avec l'attribut inputType. Cela informe simplement Android du type de texte attendu, comme une adresse e-mail, un mot de passe ou un numéro de téléphone. La liste complète des valeurs possibles est disponible ici .

C'était, cependant, l'attribut imeOptions="actionUnspecified"dont je ne comprenais pas le but. Android vous permet d'interagir avec le clavier qui apparaît du bas de l'écran lorsque le texte est sélectionné à l'aide de InputMethodManager. Dans le coin inférieur du clavier, il y a un bouton, généralement il dit "Suivant" ou "Terminé", selon le champ de texte actuel. Android vous permet de personnaliser cela en utilisant android:imeOptions. Vous pouvez spécifier un bouton "Envoyer" ou "Suivant". La liste complète peut être trouvée ici .

Avec cela, vous pouvez ensuite écouter les pressions sur le bouton d'action en définissant un TextView.OnEditorActionListenerpour l' EditTextélément. Comme dans votre exemple:

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

Maintenant, dans mon exemple, j'avais l' android:imeOptions="actionUnspecified"attribut. Ceci est utile lorsque vous souhaitez essayer de vous connecter à un utilisateur lorsqu'il appuie sur la touche Entrée. Dans votre activité, vous pouvez détecter cette balise, puis tenter de vous connecter:

    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;
        }
    });
Donato
la source
6

Merci à chikka.anddev et Alex Cohn à Kotlin c'est:

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

Ici, je vérifie la Enterclé, car elle retourne à la EditorInfo.IME_NULLplace de IME_ACTION_DONE.

Voir aussi Android imeOptions = "actionDone" ne fonctionne pas . Ajoutez android:singleLine="true"le EditText.

CoolMind
la source
6

Solution Kotlin

La façon de base de le gérer dans Kotlin est:

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

Extension Kotlin

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

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

N'oubliez pas d'ajouter ces options à votre edittext

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

Si vous avez besoin d' inputType="textMultiLine"aide, lisez cet article

Gibolt
la source
1
Excellente réponse, merci pour le partage! Je semble continuer à recevoir un avertissement de peluche concernant la valeur de retour du setOnEditorActionListener, cependant. Peut-être que c'est juste une question de paramètres de configuration locaux, mais mon linter veut vraiment, vraiment que j'ajoute une elsebranche aussi afin d'accepter le "vrai" comme une déclaration de retour de l'auditeur (par opposition au if-bloc).
dbm le
0

Si vous utilisez les annotations Android https://github.com/androidannotations/androidannotations

Vous pouvez utiliser l'annotation @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
    }
}
Rafael Rocha
la source