web-dev-qa-db-ja.com

EditTextOnKeyListenerが機能しない

私は知っています これ/同様の質問 以前に尋ねられましたが、与えられた解決策は私のために機能していないので、私はもう一度尋ねています。その回答に示されている解決策を試しましたが、それでも一部のデバイス、特にストック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;
        }
    });
10
Ammar

最後に、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をカスタマイズして、カーソル位置が変わるたびに通知しました。この目的は、onSelectionChangedEditTextメソッドをオーバーライドすることによって実現されます。カスタマイズした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);
        }
    }
});

これが同様の状況で役立つことを願っています。改善/最適化のための提案を歓迎します。

22
Ammar

ドキュメントには、キーイベントはハードウェアのキーストロークに対してのみ伝播され、ソフトウェアでは伝播されないと記載されています。

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イベント内から変更しないでください。変更すると、無限のイベント/リスニングループが発生する可能性があります。

12
Ameer

OnKeyListenerの-​​ documentation に基づくと、コールバックはハードウェアキーボードに対してのみ呼び出されるようです。

ハードウェアキーイベントがこのビューにディスパッチされたときに呼び出されるコールバックのインターフェイス定義。キーイベントがビューに渡される前に、コールバックが呼び出されます。これは、ハードウェアキーボードにのみ役立ちます。ソフトウェア入力方式には、このリスナーをトリガーする義務はありません。

4

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"
    />

値について:actionGoactionNonenormalactionSearchonKeyListenerが呼び出されたことに気づきました。

P.S.その属性を指定しなくても機能しました。

0
rehman_00001