背景
アプリの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>
図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;
}
});
図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)
アンドロイドの公式ではそういった,
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値の説明もあります.
ということで,return true;の場合にはこのlistenerはこのeventを消化する.つまり,return true;の場ありには,hardwareキーボードがこのviewに対してなんか操作する時には,onKeyを実行しなくなる.なるほどかな,