私は知っています これ/同様の質問 以前に尋ねられましたが、与えられた解決策は私のために機能していないので、私はもう一度尋ねています。その回答に示されている解決策を試しましたが、それでも一部のデバイス、特にストックOSを搭載したデバイスでOnKeyListenerが呼び出されることはありません。 editTextに文字がないときに、ソフトキーボードのdelキーが押されたことを検出する必要があります。これが私のコードです。
EditText et = (EditText) findViewById(R.id.et);
et.setOnKeyListener(new EditText.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.d("OnKeyListener", keyCode + " character(code) to send");
return false;
}
});
最後に、TextWatcher
を介してこの機能を実装することにより、自分自身を解決しました。主なハードルは、EditText
に文字がない場合、または少なくともエンドユーザーがそこに文字がないと認識している場合でも、バックスペースプレスを検出する必要があることでした。最初のことは達成できませんでしたが、私は後のことをしました。以下は詳細な解決策です。
まず、editText
には常にスペース ''文字を保持していました。
editText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
if(cs.toString().length() == 0)
editText.setText(" ");
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { }
@Override
public void afterTextChanged(Editable arg0) { }
});
次に、EditText
をカスタマイズして、カーソル位置が変わるたびに通知しました。この目的は、onSelectionChanged
のEditText
メソッドをオーバーライドすることによって実現されます。カスタマイズしたEditText
は次のようになります。
public class SelectionEnabledEditText extends EditText {
public SelectionEnabledEditText(Context context) {
super(context);
}
public SelectionEnabledEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SelectionEnabledEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
super.onSelectionChanged(selStart, selEnd);
if(onSelectionChangeListener != null)
onSelectionChangeListener.onSelectionChanged(selStart, selEnd);
}
public static interface OnSelectionChangeListener{
public void onSelectionChanged(int selStart, int selEnd);
}
private OnSelectionChangeListener onSelectionChangeListener;
public void setOnSelectionChangeListener(OnSelectionChangeListener onSelectionChangeListener) {
this.onSelectionChangeListener = onSelectionChangeListener;
}
}
最後に、私のアクティビティでは、カーソル位置変更イベントをリッスンし、必要なスペース文字の開始位置、つまり次のように0番目のインデックスにカーソル位置がある場合はeditText
でカーソル位置をリセットします。
editText.setOnSelectionChangeListener(new SelectionEnabledEditText.OnSelectionChangeListener() {
@Override
public void onSelectionChanged(int selStart, int selEnd) {
if (selEnd == 0) {
if (editText.getText().toString().length() == 0)
editText.setText(" ");
editText.setSelection(1);
}
}
});
これが同様の状況で役立つことを願っています。改善/最適化のための提案を歓迎します。
ドキュメントには、キーイベントはハードウェアのキーストロークに対してのみ伝播され、ソフトウェアでは伝播されないと記載されています。
http://developer.Android.com/reference/Android/view/View.OnKeyListener.html
デバイスメーカーは、実際にはキーリスナーを介してソフトキーボードイベントを伝播することを推奨されていませんが、それを尊重するか、実際にソフトキーボードとハードキーボードを同等の条件で扱うかはメーカー次第です。
Android 4.2.2、Androidシステム自体は、ソフトキーボードのキーストロークイベントをまったくサポートしないため、メーカーでさえサポートできません。彼らの方法を選択してください。
したがって、ここでの唯一の確実なオプションは、独自のIME(ソフトキーボード)を実装し、キーストロークを自分で処理することです。
TextWatcherは主にキーリスナーを置き換えるために使用できますが、editText.setText(...); TextWatcherイベントもトリガーされるため、型指定されたキーのみに関心がある場合は、おそらくTextWatcherも解決策ではありません。
AutocomleteTextViewまたはEditTextでTextWatcherを使用する場合は、注意してください。 AutocompleteTextView/EditTextのコンテンツ内のテキストをTextWatcherイベント内から変更しないでください。変更すると、無限のイベント/リスニングループが発生する可能性があります。
OnKeyListener
の- documentation に基づくと、コールバックはハードウェアキーボードに対してのみ呼び出されるようです。
ハードウェアキーイベントがこのビューにディスパッチされたときに呼び出されるコールバックのインターフェイス定義。キーイベントがビューに渡される前に、コールバックが呼び出されます。これは、ハードウェアキーボードにのみ役立ちます。ソフトウェア入力方式には、このリスナーをトリガーする義務はありません。
EditTextの属性があります:Android:imeOptions
<androidx.appcompat.widget.AppCompatEditText
Android:id="@+id/main_editor"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:imeOptions="actionGo"
/>
値について:actionGo
、actionNone
、normal
、actionSearch
onKeyListenerが呼び出されたことに気づきました。
P.S.その属性を指定しなくても機能しました。