👺

Android|EditTextのキーボード非表示 & focus管理

2022/07/29に公開

EditTextって割とリスナーイベント設定してキーボードの表示管理しないといけないなと思い、まとめた次第です。あと、EditTextにfocusあたったままになるので、このfocus管理方法もまとめております。
※本記事はviewBinding、navigationを用いての方法で記載しております。

キーボード非表示

まずはキーボードを非表示にする方法です。

fun showOffKeyboard() {
	val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
	imm.hideSoftInputFromWindow(binding.root.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
}

でもって、キーボードを非表示にする時って主に下記の2つかと思いますので、
それぞれのリスナーをご紹介

エンターキー押した時

binding.editText.setOnEditorActionListener { _, i, keyEvent ->
    if (i == EditorInfo.IME_ACTION_SEARCH ||
	i == EditorInfo.IME_ACTION_DONE ||
	keyEvent != null &&
	keyEvent.action == KeyEvent.ACTION_DOWN &&
	keyEvent.keyCode == KeyEvent.KEYCODE_ENTER) {
	if (keyEvent == null || !keyEvent.isShiftPressed) {
	    showOffKeyboard() // キーボード非表示
	    return@setOnEditorActionListener true
	} else {
	    return@setOnEditorActionListener false
	}
    } else {
	return@setOnEditorActionListener false
    }
}

EditText以外をタップ

ViewをタップしたときにfocusをそのままViewにして解除してあげる
Activityで呼んであげるようにする。
メリットとしてFragmentにEditTextが追加された場合でも特に追記する必要がないこと。

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
	showOffKeyboard()
	return super.dispatchTouchEvent(ev)
}

EditTextのフォーカス管理

EditTextにずっとフォーカスがあたっているので、focusをViewにあててあげることで解決します。

view.requestFocus()

そのためにはまずはfocusをあてるレイアウトにそれぞれ下記を追加して、
focusできるようにしておく必要があるので追加します。

android:focusable="true"
android:focusableInTouchMode="true"

まとめ

最後にキーボードの非表示とフォーカス管理をまとめたコードを記載します。

/** Activity内に記載 **/
// Viewタッチしたときのリスナー
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
	binding.root.requestFocus()
	return super.dispatchTouchEvent(ev)
}
/** Fragmentに記載 **/

// EditTextのフォーカス変更リスナー
binding.editText.setOnFocusChangeListener { v, hasFocus ->
  // フォーカスが外れた時に キーボード非表示
    if(!hasFocus) {
	showOffKeyboard()
    }
}

// エンターキーリスナー
binding.editText.setOnEditorActionListener { _, i, keyEvent ->
    if (i == EditorInfo.IME_ACTION_SEARCH ||
	i == EditorInfo.IME_ACTION_DONE ||
	keyEvent != null &&
	keyEvent.action == KeyEvent.ACTION_DOWN &&
	keyEvent.keyCode == KeyEvent.KEYCODE_ENTER) {
	if (keyEvent == null || !keyEvent.isShiftPressed) {
	  // フォーカスをはずす
	    binding.root.requestFocus()
	    return@setOnEditorActionListener true
	} else {
	    return@setOnEditorActionListener false
	}
    } else {
	return@setOnEditorActionListener false
    }
}

// キーボード非表示
private fun showOffKeyboard() {
	val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
	imm.hideSoftInputFromWindow(binding.root.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
}

Discussion