Android
EditText
setOnClickListener
Listener

AndroidのEditTextにsetOnKeyListenerを使う時にEditTextの内容を消せなくなる問題

背景

アプリのSearchBarにEditTextを設置して、EditTextに文字をに入力して、keyboardのEnter keyを押して検索処理を行う。EditTextにキーボード操作をさせる時には、ViewクラスのOnKeyListenerインタフェースを実装するmOnKeyListener変数のonKeyメソードメソードが実行される。
だからEditTextにキーボード操作をさせる時に何が実装したい時には、自分からViewクラスのmOnKeyListenerを定義する必要がある。ここではViewクラスのsetOnKeyListenerメソードを使って、ViewクラスのmOnKeyListener変数を定義する。

FragmentListenerActivity.java

public class FragmentListenerActivity extends AppCompatActivity {


    private ArrayList<String> mList = null;
    private Context mContext = null;
    private ListView mListView = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment_listener);

        final EditText mEditText = (EditText) findViewById(R.id.mEdit);

        mEditText.setOnKeyListener(new View.OnKeyListener() {
            public boolean onKey(View v, int keyCode, KeyEvent event) {

                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if ((keyCode == KeyEvent.KEYCODE_ENTER) ||
                            (keyCode == KeyEvent.KEYCODE_DPAD_CENTER)) {
                            String res = mEditText.getText().toString();
                            ((TextView)findViewById(R.id.mText)).setText(res);
                    }
                }
                return true;
            }
        });
    }
}

activity_fragment_listener.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.example.syoui.imagetab.foundation.fragment.FragmentListenerActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <EditText
            android:id="@+id/mEdit"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/mText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</android.support.constraint.ConstraintLayout>

SVID_20180114_222813(2).gif
図1

図1のように,キーボードのEnterキーを押したら,またdeleteキーを消したら,意外にEditTextの内容が消えなくなる問題だ.社内の先輩の方聞いたらFragmentListenerActivity.javaを以下のように変えたら,もう消せるようになる.

        mEditText.setOnKeyListener(new View.OnKeyListener() {
            public boolean onKey(View v, int keyCode, KeyEvent event) {

                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if ((keyCode == KeyEvent.KEYCODE_ENTER) ||
                            (keyCode == KeyEvent.KEYCODE_DPAD_CENTER)) {
                            String res = mEditText.getText().toString();
                            ((TextView)findViewById(R.id.mText)).setText(res);
                    }
                }
                //return true;
                return false;
            }
        });

SVID_20180114_225050.gif
図2

図2のように,Enterキーを押して入力した内容を確定したら,deleteキーを押したらEditTextの内容もどんどん消していった.
ソースコードで編集した内容は,ただ一行たけで
onKeyの実装の最後には
return true;ではなく 
return false;です!

原因としては,return trueしたら,このEditTextのonKeyの実行はもう他のところから呼べなくなる.onKeyのメソードを呼ぶのはここではなく,deleteキーを押すときには他のどこかにもこのonKeyメソードも呼んでいるから,ここでのonKey処理が終わったら,return falseで,次の処理に回すべきだ.
[アンドロイドの公式説明](https://developer.android.com/reference/android/view/View.OnKeyListener.html)

アンドロイドの公式ではそういった,

スクリーンショット 2018-01-14 23.13.58.png
図3

Interface definition for a callback to be invoked when a hardware key event is dispatched to this view. The callback will be invoked before the key event is given to the view. This is only useful for hardware keyboards; a software input method has no obligation to trigger this listener.

つまり,hardwareキーボードでこのviewに対して操作するときにこのonKeyメソードの内容を実行する.我々は定義したonKeyのところもちろん実行するが,他のところの実行するだろう.
もっと見たら,Return値の説明もあります.

スクリーンショット 2018-01-14 23.15.48.png
図4

ということで,return true;の場合にはこのlistenerはこのeventを消化する.つまり,return true;の場ありには,hardwareキーボードがこのviewに対してなんか操作する時には,onKeyを実行しなくなる.なるほどかな,