152 votes

Événement de touche EditText delete(backspace) d'Android

Comment puis-je détecter l'événement de la touche de suppression (backspace) pour un editText ? J'ai essayé d'utiliser TextWatcher, mais lorsque l'editText est vide, lorsque j'appuie sur la touche delete, rien ne se passe. Je veux détecter l'appui sur la touche de suppression pour un editText même s'il n'a pas de texte.

212voto

Labeeb P Points 12645

NOTA: onKeyListener ne fonctionne pas pour les claviers souples.

Vous pouvez définir OnKeyListener pour vous editText afin de pouvoir détecter toute pression sur une touche
EDIT : Une erreur commune que nous vérifions KeyEvent.KEYCODE_BACK para backspace mais en réalité, c'est KeyEvent.KEYCODE_DEL (Vraiment, ce nom est très déroutant !)

editText.setOnKeyListener(new OnKeyListener() {                 
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        //You can identify which key pressed buy checking keyCode value with KeyEvent.KEYCODE_
        if(keyCode == KeyEvent.KEYCODE_DEL) {  
            //this is for backspace
        }
        return false;       
    }
});

13 votes

Je viens d'essayer, mais les onKeyListeners n'enregistrent apparemment pas les backspaces.

8 votes

Il ne fonctionnera pas pour le clavier souple. Cela ne fonctionnera que pour l'entrée matérielle.

6 votes

Sur mon Nexus4 (fonctionnant sous KitKat standard), ceci fait travail pour le clavier logiciel.

92voto

Idris Points 648

Cela fait un moment que vous avez posé la question mais je viens d'avoir le même problème. Comme déjà mentionné par Estel, le problème avec les key listeners est qu'ils ne fonctionnent qu'avec les claviers matériels. Pour faire cela avec un IME (clavier souple) la solution est un peu plus élaborée.

La seule méthode que nous voulons réellement surcharger est sendKeyEvent dans le EditText 's InputConnection classe. Cette méthode est appelée lorsque des événements clés se produisent dans une EMI. Mais pour remplacer cette méthode, nous devons implémenter une méthode d'appel personnalisée. EditText qui remplace le onCreateInputConnection en enveloppant la méthode par défaut InputConnection dans une classe proxy ! :|

Cela semble compliqué, mais voici l'exemple le plus simple que j'ai pu inventer :

public class ZanyEditText extends EditText {

    private Random r = new Random();

    public ZanyEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public ZanyEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ZanyEditText(Context context) {
        super(context);
    }

    public void setRandomBackgroundColor() {
        setBackgroundColor(Color.rgb(r.nextInt(256), r.nextInt(256), r
                .nextInt(256)));
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        return new ZanyInputConnection(super.onCreateInputConnection(outAttrs),
                true);
    }

    private class ZanyInputConnection extends InputConnectionWrapper {

        public ZanyInputConnection(InputConnection target, boolean mutable) {
            super(target, mutable);
        }

        @Override
        public boolean sendKeyEvent(KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_DOWN
                    && event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
                ZanyEditText.this.setRandomBackgroundColor();
                // Un-comment if you wish to cancel the backspace:
                // return false;
            }
            return super.sendKeyEvent(event);
        }

    }

}

La ligne avec l'appel à setRandomBackgroundColor est l'endroit où se produit mon action spéciale de retour en arrière. Dans ce cas, changer le EditText La couleur d'arrière-plan de l'entreprise.

Si vous le gonflez à partir de XML, n'oubliez pas d'utiliser le nom complet du paquet comme balise :

<cc.buttfu.test.ZanyEditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/somefield"
></cc.buttfu.test.ZanyEditText>

28 votes

J'ai récemment rencontré le même problème avec Jelly Bean. J'ai trouvé que cette solution fonctionnait en grande partie, sauf que j'ai dû remplacer deleteSurroundingText(...) par sendKeyEvent(...) (qui n'était pas appelé du tout). J'espère que cela aidera quelqu'un d'autre !

0 votes

Cette réponse, combinée au commentaire de @Brandon ci-dessus, m'a permis d'obtenir ce résultat. Ce que je me demande maintenant, c'est comment cela va fonctionner sur les appareils pré-JellyBean.

0 votes

Cela fonctionne avec la réponse acceptée sur les appareils 2.2 et 2.3 pour moi.

76voto

jlbruno Points 2026

Il s'agit simplement d'un ajout à la réponse d'Idris, en ajoutant également la surcharge de deleteSurroundingText. J'ai trouvé plus d'informations à ce sujet ici : Android : Espace arrière dans WebView/BaseInputConnection

package com.elavon.virtualmerchantmobile.utils;

import java.util.Random;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
import android.widget.EditText;

public class ZanyEditText extends EditText {

    private Random r = new Random();

    public ZanyEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public ZanyEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ZanyEditText(Context context) {
        super(context);
    }

    public void setRandomBackgroundColor() {
        setBackgroundColor(Color.rgb(r.nextInt(256), r.nextInt(256), r
                .nextInt(256)));
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        return new ZanyInputConnection(super.onCreateInputConnection(outAttrs),
                true);
    }

    private class ZanyInputConnection extends InputConnectionWrapper {

        public ZanyInputConnection(InputConnection target, boolean mutable) {
            super(target, mutable);
        }

        @Override
        public boolean sendKeyEvent(KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_DOWN
                    && event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
                ZanyEditText.this.setRandomBackgroundColor();
                // Un-comment if you wish to cancel the backspace:
                // return false;
            }
            return super.sendKeyEvent(event);
        }

        @Override
        public boolean deleteSurroundingText(int beforeLength, int afterLength) {       
            // magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace
            if (beforeLength == 1 && afterLength == 0) {
                // backspace
                return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
                    && sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
            }

            return super.deleteSurroundingText(beforeLength, afterLength);
        }

    }

}

3 votes

Merci ! Le site deleteSurroundingText bit était exactement ce dont j'avais besoin après avoir essayé d'autres solutions.

5 votes

Cette solution a très bien fonctionné pour moi sur les versions précédentes d'Android, mais malheureusement deleteSurroundingText n'est appelé que lors de la suppression des espaces blancs sur 4.4(KitKat). J'ai testé sur les Nexus4 et 7.

1 votes

Il semble que deleteSurroundingText soit nécessaire lorsque l'EditText est multiligne. Étrange

27voto

Leo Droidcoder Points 5410

Voici ma solution facile, qui fonctionne pour toutes les API :

private int previousLength;
private boolean backSpace;

// ...

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    previousLength = s.length();
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}

@Override
public void afterTextChanged(Editable s) {
    backSpace = previousLength > s.length();

    if (backSpace) {

        // do your stuff ...

    } 
}

MISE À JOUR 17.04.18 .
Comme cela a été souligné dans les commentaires, cette solution ne suit pas l'appui sur le retour arrière si l'EditText est vide (comme la plupart des autres solutions).
Cependant, c'est suffisant pour la plupart des cas d'utilisation.
P.S. Si je devais créer quelque chose de similaire aujourd'hui, je le ferais :

public abstract class TextWatcherExtended implements TextWatcher {

    private int lastLength;

    public abstract void afterTextChanged(Editable s, boolean backSpace);

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        lastLength = s.length();
    }

    @Override
    public void afterTextChanged(Editable s) {
        afterTextChanged(s, lastLength > s.length());
    }  
}

Ensuite, il suffit de l'utiliser comme un TextWatcher normal :

 editText.addTextChangedListener(new TextWatcherExtended() {
        @Override
        public void afterTextChanged(Editable s, boolean backSpace) {
           // Here you are! You got missing "backSpace" flag
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // Do something useful if you wish.
            // Or override it in TextWatcherExtended class if want to avoid it here 
        }
    });

11voto

J.P Points 137

J'ai mis 2 jours pour trouver une solution et j'en ai trouvé une qui fonctionne :) (sur les touches programmables)

public TextWatcher textWatcher = new TextWatcher() {
@Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {   } 

@Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        if (count == 0) {
        //Put your code here.
        //Runs when delete/backspace pressed on soft key (tested on htc m8)
        //You can use EditText.getText().length() to make if statements here
        }
    }

@Override
    public void afterTextChanged(Editable s) {
    }
}

Après avoir ajouté le textwatcher à votre EditText :

yourEditText.addTextChangedListener(textWatcher);

J'espère qu'il fonctionne aussi sur d'autres appareils Android (Samsung, LG, etc.).

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