Android EditText supprimer l'événement clé (backspace)

Comment puis-je détecter un événement clé delete (backspace) pour un texte électronique? J'ai essayé D'utiliser TextWatcher, mais quand le texte est vide, quand j'appuie sur Supprimer la touche, rien ne se passe. Je veux détecter supprimer la touche presser pour un texte édité même s'il n'a pas de texte.

90
demandé sur Brian Tompsett - 汤莱恩 2011-02-03 16:45:12

15 réponses

NOTE: onKeyListener ne fonctionne pas pour les claviers souples.

vous pouvez définir OnKeyListener pour vous editText ainsi vous pouvez détecter n'importe quelle pression de touche

EDIT: une erreur courante nous vérifions KeyEvent.KEYCODE_BACK pour backspace , mais en réalité c'est KeyEvent.KEYCODE_DEL (vraiment ce nom est très confus! )

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;       
    }
});
113
répondu Labeeb Panampullan 2018-04-17 23:53:02

ça fait longtemps que vous n'avez pas demandé, mais j'ai eu le même problème. Comme déjà mentionné par Estel le problème avec les écouteurs clés est qu'ils ne fonctionnent qu'avec les claviers matériels. Pour ce faire, avec un IME (clavier) , la solution est un peu plus élaboré.

la seule méthode que nous voulons réellement remplacer est sendKeyEvent dans la classe EditText 's InputConnection . Cette méthode est appelée lorsque des événements clés se produisent dans un EMI. Mais dans pour l'annuler, nous devons implémenter un custom EditText qui remplace la méthode onCreateInputConnection , enveloppant l'objet par défaut InputConnection dans une classe proxy! : /

semble compliqué, mais voici l'exemple le plus simple que je pourrais 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ù mon action backspace spéciale se produit. Dans ce cas, changer la couleur de fond du EditText .

si vous gonflez ceci à partir de XML n'oubliez pas d'utiliser le nom complet du paquet comme étiquette:

<cc.buttfu.test.ZanyEditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/somefield"
></cc.buttfu.test.ZanyEditText>
74
répondu Idris 2012-07-07 18:10:41

ce n'est qu'un ajout à la réponse D'Idris, ajoutant dans la commande de remplacement deleteSurroundingText ainsi. J'ai trouvé plus d'informations sur ce ici: Android: Backspace in 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);
        }

    }

}
58
répondu Jeff 2017-05-23 12:10:30

voici ma solution facile, qui fonctionne pour tous 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 indiqué dans les commentaires, Cette solution ne trace pas la presse backspace si EditText est vide (la même que la plupart des autres solutions).

Cependant, il est suffisant pour la plupart des cas d'utilisation.

p. SI je devais créer quelque chose de semblable aujourd'hui, je 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());
    }  
}

alors il suffit de l'utiliser comme un TextWatcher régulier:

 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 
        }
    });
18
répondu Leo Droidcoder 2018-04-17 20:06:10

j'ai envoyé 2 jours pour trouver une solution et j'ai trouvé un travail :) (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 ajouter le textwatcher à votre texte D'édition:

yourEditText.addTextChangedListener(textWatcher);

j'espère qu'il fonctionne sur d'autres appareils android aussi (samsung, LG, etc).

10
répondu J.P 2016-05-24 16:15:37

exemple de création D'EditText avec TextWatcher

EditText someEdit=new EditText(this);
//create TextWatcher for our EditText
TextWatcher1 TW1 = new TextWatcher1(someEdit);
//apply our TextWatcher to EditText
        someEdit.addTextChangedListener(TW1);

personnalisé TextWatcher

public class TextWatcher1 implements TextWatcher {
        public EditText editText;
//constructor
        public TextWatcher1(EditText et){
            super();
            editText = et;
//Code for monitoring keystrokes
            editText.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if(keyCode == KeyEvent.KEYCODE_DEL){
                        editText.setText("");
                    }
                        return false;
                }
            });
        }
//Some manipulation with text
        public void afterTextChanged(Editable s) {
            if(editText.getText().length() == 12){
                editText.setText(editText.getText().delete(editText.getText().length() - 1, editText.getText().length()));
                editText.setSelection(editText.getText().toString().length());
            }
            if (editText.getText().length()==2||editText.getText().length()==5||editText.getText().length()==8){
                editText.setText(editText.getText()+"/");
                editText.setSelection(editText.getText().toString().length());
            }
        }
        public void beforeTextChanged(CharSequence s, int start, int count, int after){
        }
        public void onTextChanged(CharSequence s, int start, int before, int count) {



        }
    }
3
répondu Alex Bigalo 2015-07-02 19:16:31

ma solution simple qui fonctionne parfaitement. Vous devez ajouter un drapeau. Mon extrait de code:

editText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            if (after < count) {
                isBackspaceClicked = true;
            } else {
                isBackspaceClicked = false;
            }
        }

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

        @Override
        public void afterTextChanged(Editable s) {
            if (!isBackspaceClicked) {
                // Your current code
            } else {
                // Your "backspace" handling
            }
        }
2
répondu EAMax 2018-05-07 10:56:36

il y a une question semblable dans le débordement des piles. Vous devez remplacer EditText afin d'obtenir l'accès à InputConnection objet qui contient la méthode deleteSurroundingText . Il vous aidera à détecter l'événement de suppression (backspace). S'il vous plaît, jetez un oeil à une solution que j'ai fourni là Android - ne peut pas capturer backspace/supprimer la presse dans soft. clavier

0
répondu Sa Qada 2017-05-23 10:31:17

Cela semble fonctionner pour moi :

public void onTextChanged(CharSequence s, int start, int before, int count) {
    if (before - count == 1) {
        onBackSpace();
    } else if (s.subSequence(start, start + count).toString().equals("\n")) {
        onNewLine();
    }
}
0
répondu rocker99 2017-04-01 06:24:36

je suis également confronté à la même question dans le dialogue.. parce que j'utilise setOnKeyListener.. Mais j'ai mis par défaut renvoie la valeur true. Après le changement comme ci-dessous le code il fonctionne très bien pour moi..

    mDialog.setOnKeyListener(new Dialog.OnKeyListener() {

        @Override
        public boolean onKey(DialogInterface arg0, int keyCode,
                             KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                mDialog.dismiss();
                return true;
            }
            return false;//this line is important 

        }
    });
0
répondu Ranjith Kumar 2017-07-15 10:07:28

basé sur @Jiff ZanyEditText voici WiseEditText avec setSoftKeyListener(OnKeyListener)

package com.locopixel.seagame.ui.custom;

import java.util.Random;

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

public class WiseEditText extends AppCompatEditText {

    private Random r = new Random();
    private OnKeyListener keyListener;

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

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

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

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

    private class MyInputConnection extends InputConnectionWrapper {

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

        @Override
        public boolean sendKeyEvent(KeyEvent event) {
            if (keyListener != null) {
                keyListener.onKey(WiseEditText.this,event.getKeyCode(),event);
            }
            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);
        }

    }

    public void setSoftKeyListener(OnKeyListener listener){
        keyListener = listener;
    }

}
0
répondu Qamar 2017-08-02 12:47:26

mon problème était, que j'avais personnalisé Textwatcher , donc je ne voulais pas ajouter OnKeyListener à un EditText ainsi que je ne voulais pas créer personnalisé EditText . Je voulais détecter si l'espace arrière était pressé dans ma méthode afterTextChanged , donc je ne devrais pas déclencher mon événement.

voilà comment j'ai résolu ça. Espérons qu'il serait utile pour quelqu'un.

public class CustomTextWatcher extends AfterTextChangedTextWatcher {

private boolean backspacePressed;

@Override
public void afterTextChanged(Editable s) {
    if (!backspacePressed) {
        triggerYourEvent();
    }
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    super.onTextChanged(s, start, before, count);
    backspacePressed = count == 0; //if count == 0, backspace is pressed
}
}
0
répondu Dmitry Smolyaninov 2017-10-02 10:12:05

j'ai testé la solution de @Jeff sur les versions 4.2, 4.4, 6.0. Sur 4.2 et 6.0, ça marche bien. Mais sur la 4.4, ça ne marche pas.

j'ai trouvé un moyen facile de contourner ce problème. Le point clé est d'insérer un caractère invisible dans le contenu D'EditText dès le début, et de ne pas laisser l'utilisateur déplacer le curseur avant ce caractère. Ma façon est d'insérer un caractère d'espace blanc avec une ImageSpan de Largeur Nulle. Voici mon code.

                @Override
                public void afterTextChanged(Editable s) {
                    String ss = s.toString();
                    if (!ss.startsWith(" ")) {
                        int selection = holder.editText.getSelectionEnd();
                        s.insert(0, " ");
                        ss = s.toString();
                        holder.editText.setSelection(selection + 1);
                    }
                    if (ss.startsWith(" ")) {
                        ImageSpan[] spans = s.getSpans(0, 1, ImageSpan.class);
                        if (spans == null || spans.length == 0) {
                            s.setSpan(new ImageSpan(getResources().getDrawable(R.drawable.zero_wdith_drawable)), 0 , 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                    }
                }

et nous avons besoin d'un texte D'édition personnalisé qui a un Sélectionchangelistener

public class EditTextSelectable extends android.support.v7.widget.AppCompatEditText {
public interface OnSelectChangeListener {
    void onSelectChange(int start, int end);
}

private OnSelectChangeListener mListener;

public void setListener(OnSelectChangeListener listener) {
    mListener = listener;
}

...constructors...

@Override
protected void onSelectionChanged(int selStart, int selEnd) {
    if (mListener != null) {
        mListener.onSelectChange(selStart, selEnd);
    }
    super.onSelectionChanged(selStart, selEnd);
}

}

et la dernière étape

holder.editText.setListener(new EditTextSelectable.OnSelectChangeListener() {
                @Override
                public void onSelectChange(int start, int end) {
                    if (start == 0 && holder.editText.getText().length() != 0) {
                        holder.editText.setSelection(1, Math.max(1, end));
                    }
                }
            });

et maintenant, nous avons terminé~ nous pouvons détecter l'événement clé backspace lorsque EditText n'a pas de contenu réel, et l'utilisateur ne saura rien de notre astuce.

0
répondu passerbywhu 2017-11-24 13:29:56

cette question est peut-être ancienne, mais la réponse est très simple en utilisant un TextWatcher.

int lastSize=0;
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    //2. compare the old length of the text with the new one
    //3. if the length is shorter, then backspace was clicked
    if (lastSize > charSequence.length()) {
        //4. Backspace was clicked
        //5. perform action
    }
    //1. get the current length of of the text
    lastSize = charSequence.length();
}
0
répondu BluRe.CN 2017-12-05 18:14:45

, Vous pouvez définir un écouteur sur l'activité, et dans la méthode de rappel, vous pourriez détecter qui touche à l'utilisateur de frapper. Le code ci-dessous pour votre référence. Espérons que cela aide.

//after user hits keys, this method would be called.
public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (editText.isFocused()) {
            switch (keyCode) {
            case KeyEvent.KEYCODE_DEL:  //delete key
                Log.i("INFO", "delete key hit"); //you should see this log in ddms after you hit delete key
                break;
            }
        }
        return super.onKeyUp(keyCode, event);
    }
-4
répondu Huang 2013-01-13 00:28:11