回答:
注:onKeyListener
ソフトキーボードでは機能しません。
キーを押すことを検出できるように設定OnKeyListener
することeditText
ができます
編集:私たちがチェックKeyEvent.KEYCODE_BACK
しているよくある間違いですbackspace
が、実際にはそうですKeyEvent.KEYCODE_DEL
(本当にその名前は非常に混乱しています!)
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;
}
});
event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_DEL
バックスペースのプレスごとに2回イベントを発生させたくない場合に使用します
質問して久しぶりですが、同じ問題が発生しました。Estelがすでに述べたように、キーリスナーの問題は、ハードウェアキーボードでしか機能しないことです。IME(ソフトキーボード)でこれを行うには、解決策はもう少し複雑です。
実際にオーバーライドする単一のメソッドはsendKeyEvent
、EditText
のInputConnection
クラスにあります。このメソッドは、IMEでキーイベントが発生したときに呼び出されます。しかし、EditText
これをオーバーライドするには、onCreateInputConnection
メソッドをオーバーライドするカスタムを実装し、デフォルトInputConnection
オブジェクトをプロキシクラスでラップする必要があります。:|
複雑に聞こえますが、ここで私が考案した最も簡単な例を示します。
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);
}
}
}
呼び出し先の行setRandomBackgroundColor
は、特別なバックスペースアクションが発生する場所です。この場合、EditText
の背景色を変更します。
XMLからこれを拡張する場合は、タグとして完全なパッケージ名を使用することを忘れないでください。
<cc.buttfu.test.ZanyEditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/somefield"
></cc.buttfu.test.ZanyEditText>
これはイドリスの答えへの追加であり、オーバーライドにdeleteSurroundingTextも追加しています。詳細については、こちらをご覧ください:Android: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);
}
}
}
deleteSurroundingText
他の無数のソリューションを試した後、ビットはまさに私が必要としたものでした。
これが私のすべての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 ...
}
}
アップデート17.04.18。
コメントで指摘されているように、EditTextが空の場合、このソリューションはバックスペースプレスを追跡しません(他のほとんどのソリューションと同じ)。
ただし、ほとんどのユースケースではこれで十分です。
PSもし私が今日同様のものを作成しなければならなかったら、私はそうするでしょう:
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());
}
}
次に、それを通常の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
}
});
解決策を見つけるために2日間送信し、実際に機能するものを見つけました:)(ソフトキーについて)
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) {
}
}
EditWatchにtextwatcherを追加した後:
yourEditText.addTextChangedListener(textWatcher);
他のAndroidデバイス(samsung、LGなど)でも動作することを願っています。
完璧に機能する私のシンプルなソリューション。フラグを追加する必要があります。私のコードスニペット:
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
}
}
TextWatcherでEditTextを作成する例
EditText someEdit=new EditText(this);
//create TextWatcher for our EditText
TextWatcher1 TW1 = new TextWatcher1(someEdit);
//apply our TextWatcher to EditText
someEdit.addTextChangedListener(TW1);
カスタム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) {
}
}
Kotlinを使用している人のために
addOnTextChanged
一部のケースを処理するのに十分な柔軟性がない(例:編集テキストが空のときにユーザーが削除を押したかどうかを検出する)
setOnkeyListener
ソフトキーボードやハードキーボードでも機能しました!しかし、いくつかのデバイス上で。私の場合、Samsung s8では機能しますが、Xiaomi mi8 seでは機能しません。
kotlinを使用している場合は、crossline関数を使用できますdoOnTextChanged
。これは同じaddOnTextChanged
ですが、編集テキストが空の場合でもコールバックがトリガーされます。
注:doOnTextChangedはAndroid KTXライブラリの一部です
doOnTextChanged
拡張機能がAndroid KTXライブラリでアクセス可能であることを指定するかもしれません
EditText
ませんか?事前の感謝
Stackoverflowにも同様の質問があります。メソッドを含むオブジェクトEditText
にアクセスするには、オーバーライドする必要があります。削除(バックスペース)イベントを検出するのに役立ちます。Androidで提供した解決策をご覧ください。バックスペースをキャプチャできません。ソフトでプレスを削除できません。キーボードInputConnection
deleteSurroundingText
Dialogでも同じ問題に直面しています。setOnKeyListenerを使用しているためです。しかし、デフォルトの戻り値をtrueに設定しています。以下のコードのような変更の後、それは私にとってはうまくいきます。
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
}
});
@Jiffに基づいて、ZanyEditText
ここにあるWiseEditText
と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;
}
}
私の問題は、私がカスタムを持っていたTextwatcher
ので、に追加OnKeyListener
したくなかったし、EditText
カスタムを作成したくなかったということでしたEditText
。afterTextChanged
メソッドでバックスペースが押されたかどうかを検出したかったので、イベントをトリガーしないでください。
これは私がこれを解決した方法です。それが誰かのために役立つことを願っています。
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
}
}
@Jeffのソリューションをバージョン4.2、4.4、6.0でテストしました。4.2と6.0では、うまく動作します。しかし、4.4では機能しません。
この問題を回避する簡単な方法を見つけました。重要な点は、最初にEditTextのコンテンツに非表示の文字を挿入し、ユーザーがこの文字の前にカーソルを移動できないようにすることです。私の方法は、幅がゼロのImageSpanを含む空白文字を挿入することです。これが私のコードです。
@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);
}
}
}
そして、SelectionChangeListenerを持つカスタムEditTextが必要です。
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);
}
}
そして最後のステップ
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));
}
}
});
これで完了です。EditTextに実際のコンテンツがなく、ユーザーが私たちのトリックについて何も知らないときに、バックスペースキーイベントを検出できます。
この質問は古いかもしれませんが、答えは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();
}
アクティビティにキーリスナーを設定し、コールバックメソッドで、ユーザーがヒットしたキーを検出できます。以下のコードは参照用です。それが役に立てば幸い。
//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);
}