事象
EditTextにOnKeyListenerをセットして、キーボードのEnterキーまたは端末の戻るボタンをクリックした際にViewModelで定義した入力完了処理を呼び出す実装をしていました。
しかし、実際にアプリを動かしてみるとEditTextで文字入力を始めようとしたところキーボードが全く反応しませんでした。
問題
下記が実際のコードです。
EditText(context).apply {
setOnKeyListener { _, keyCode, keyEvent ->
if ((keyEvent.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) ||
(keyEvent.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK)
) viewModel.onCompleteEdit()
return@setOnKeyListener true
}
}
上記コードではsetOnKeyListener(View.OnKeyListener)
の戻り値が常にtrue
になっています。
ここからは理解が合っているか不安な部分ではありますが、、、
この実装のままだと全てのキーイベントをリスナー側で消費することになり、実際にそのキーが押された際の動作までイベントが届かないようになってしまいます。
解決策
if文に入れた条件以外のキーイベントは消費したくないので、if文に入った時とそれ以外で返却する値を変えました。
EditText(context).apply {
setOnKeyListener { _, keyCode, keyEvent ->
if ((keyEvent.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) ||
(keyEvent.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK)
) {
viewModel.onCompleteEdit()
return@setOnKeyListener true
}
return@setOnKeyListener false
}
}
上記の実装で無事にキーボードが反応するようになりました。
おまけ
このコードを書いていた時はエミュレータで開発していたのですが、エミュレータでは動いていたので実機で触るまで気付きませんでした。
実機とエミュレータだとキーボードの仕様が違うのでしょうか。
少し調べてみたところ、そもそもView.OnKeyListener
はハードウェアキーボードに対するイベントを通知するものであって、ソフトウェアキーボードのイベントが必ずしも通知されるとは限らないみたいです。
https://developer.android.com/reference/android/view/View.OnKeyListener