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.
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;
}
});
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>
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);
}
}
}
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
}
});
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.).
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) {
}
}
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
}
}
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ß.
für jemanden, der Kotlin benutzt
addOnTextChanged
ist 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.
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
}
});
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;
}
}
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();
}
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();
}
}
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
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
}
}
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
}
}
}