it-swarm.com.de

Android EditText-Löschereignis (Rücktaste)

Wie kann ich ein Schlüsselereignis (Rücktaste) für einen editText erkennen? Ich habe versucht, TextWatcher zu verwenden, aber wenn der editText leer ist, wenn ich die Löschtaste drücke, passiert nichts. Ich möchte die Löschtaste erkennen, wenn Sie einen editText eingeben, auch wenn er keinen Text enthält. 

98
Buda Gavril

HINWEIS: onKeyListener funktioniert nicht für Soft-Tastaturen.

Sie können OnKeyListener für Sie editText einstellen, damit Sie jeden Tastendruck erkennen können
EDIT: Ein häufiger Fehler, den wir KeyEvent.KEYCODE_BACK auf backspace prüfen, aber es ist wirklich KeyEvent.KEYCODE_DEL (Der Name ist wirklich sehr verwirrend!)

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

Es ist schon eine Weile her, seit du gefragt hast, aber ich hatte gerade das gleiche Problem. Wie bereits von Estel erwähnt, besteht das Problem bei den Key-Listenern darin, dass sie nur mit Hardwaretastaturen arbeiten. Um dies mit einer IME (Soft-Tastatur) zu erreichen, ist die Lösung etwas komplizierter. 

Die einzige Methode, die wir eigentlich überschreiben möchten, ist sendKeyEvent in der EditText-Klasse von InputConnection. Diese Methode wird aufgerufen, wenn Schlüsselereignisse in einem IME auftreten. Um dies zu überschreiben, müssen Sie jedoch ein benutzerdefiniertes EditText implementieren, das die onCreateInputConnection-Methode überschreibt und das standardmäßige InputConnection-Objekt in eine Proxy-Klasse umschließt! : |

Hört sich kompliziert an, aber hier ist das einfachste Beispiel, das ich mir vorstellen konnte:

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

    }

}

In der Zeile mit dem Aufruf von setRandomBackgroundColor findet meine spezielle Rücktaste statt. Ändern Sie in diesem Fall die Hintergrundfarbe von EditText.

Wenn Sie dies aus XML aufblasen, verwenden Sie den vollständigen Paketnamen als Tag:

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

Dies ist nur eine Ergänzung zu Idris 'Antwort, die auch deleteSurroundingText überschreibt. Weitere Informationen dazu habe ich hier gefunden: Android: Rücktaste 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);
        }

    }

}
60
Jeff

Hier ist meine einfache Lösung, die für alle APIs funktioniert:

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

    } 
}

UPDATE 17.04.18 .
Wie in Kommentaren darauf hingewiesen wurde, verfolgt diese Lösung nicht die Rücktaste, wenn EditText leer ist (wie bei den meisten anderen Lösungen).
Für die meisten Anwendungsfälle reicht es jedoch aus.
P.S. Wenn ich heute etwas Ähnliches erstellen müsste, würde ich Folgendes tun:  

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

Dann verwenden Sie es einfach als normaler TextWatcher:

 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 
        }
    });
22
Leo Droidcoder

Ich habe 2 Tage geschickt, um eine Lösung zu finden und eine funktionierende Lösung herauszufinden :) (auf Softkeys)

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

Nachdem Sie den Textwatcher zu Ihrem EditText hinzugefügt haben:

yourEditText.addTextChangedListener(textWatcher);

Ich hoffe, es funktioniert auch auf anderen Android-Geräten (Samsung, LG usw.).

11
J.P

Beispiel zum Erstellen von EditText mit TextWatcher

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

benutzerdefinierter 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
Alex Bigalo

Meine einfache Lösung, die perfekt funktioniert. Sie sollten eine Flagge hinzufügen. Mein Code-Snippet:

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

Ich habe die Lösung von @ Jeff auf Version 4.2, 4.4, 6.0 getestet. In 4.2 und 6.0 funktioniert es gut. Aber auf 4.4 funktioniert es nicht. 

Ich habe einen einfachen Weg gefunden, um dieses Problem zu umgehen. Der Schlüsselpunkt ist, ein unsichtbares Zeichen zu Beginn in den Inhalt von EditText einzufügen und den Benutzer nicht vor diesem Zeichen bewegen zu lassen. Mein Weg ist, ein Leerzeichen mit einem ImageSpan von null Breite einzufügen. Hier ist mein 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);
                        }
                    }
                }

Und wir brauchen einen EditText, der einen SelectionChangeListener hat

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

}

Und der letzte Schritt

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

Und jetzt sind wir fertig ~ Wir können ein Backspace-Schlüsselereignis erkennen, wenn EditText keinen tatsächlichen Inhalt hat und der Benutzer nichts über unseren Trick weiß.

0
passerbywhu

für jemanden, der Kotlin benutzt

addOnTextChangedist nicht flexibel genug um einige Fälle zu behandeln (Beispiel: Ermitteln, ob der Benutzer die Entf-Taste gedrückt hat, als der Bearbeitungstext leer war)

setOnkeyListener funktionierte sogar mit Softkeyboards oder Hardkeyboards! aber nur bei einigen Geräten. In meinem Fall funktioniert es auf Samsung s8, aber nicht auf Xiaomi mi8 se.

wenn Sie Kotlin verwenden, können Sie die Kreuzlinienfunktion doOnTextChanged verwenden. Sie ist dieselbe wie addOnTextChanged, aber der Rückruf wird ausgelöst, selbst wenn der bearbeitete Text leer war.

0

Ich bin auch mit demselben Problem in Dialog konfrontiert .. weil ich setOnKeyListener verwende. Nach dem Ändern wie unter Code funktioniert es gut für mich .. 

    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
Ranjith Kumar

Basierend auf @Jiff ZanyEditText ist hier WiseEditText mit 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
Qamar

Diese Frage mag alt sein, aber die Antwort ist mit einem TextWatcher sehr einfach.

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
BluRe.CN

Das scheint für mich zu funktionieren:

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
rocker99

Es gibt eine ähnliche Frage im Stackoverflow. Sie müssen EditText überschreiben, um auf das InputConnection-Objekt zugreifen zu können, das die deleteSurroundingText-Methode enthält. Es hilft Ihnen, Löschungsereignisse (Rücktaste) zu erkennen. Bitte schauen Sie sich eine Lösung an, die ich dort bereitgestellt habe Android - kann keine Rücktaste erfassen/löschen. Tastatur

0
Sa Qada

Mein Problem war, dass ich benutzerdefinierte Textwatcher hatte, also wollte ich OnKeyListener nicht zu einer EditText hinzufügen und wollte auch keine benutzerdefinierten EditText erstellen. Ich wollte herausfinden, ob die Rücktaste in meiner afterTextChanged-Methode gedrückt wurde, sodass ich mein Ereignis nicht auslösen sollte.

So habe ich das gelöst. Ich hoffe es wäre für jemanden hilfreich.

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

Ich habe eine wirklich einfache Lösung gefunden, die mit einer Softtastatur funktioniert.

override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) {
    text?.let { 
        if(count < before) {
            Toast.makeText(context, "backspace pressed", Toast.LENGTH_SHORT).show()
            // implement your own code
        }
    }
}
0
Hawklike