有个常见的需求,就是在页面上编辑时打开输入法,点击其他位置时收起输入法。
我们可以在基类的 Activity 去实现这个需求:
abstract class BaseActivity : AppCompatActivity() {
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
if (shouldHideSoftInput(ev)) hideSoftInput()
return super.dispatchTouchEvent(ev)
}
/** 当前事件[ev]是否应该隐藏输入法 */
private fun shouldHideSoftInput(ev: MotionEvent): Boolean {
return ev.action == MotionEvent.ACTION_DOWN
&& !isInEditTextRange(ev.x.toInt(), ev.y.toInt())
}
/** 指定位置([x],[y])是否在 EditText 的范围中 */
private fun isInEditTextRange(x: Int, y: Int): Boolean {
window.decorView.getFocusables(View.FOCUS_FORWARD).forEach {
if (it.visibility == View.GONE) return@forEach
if (it is EditText && isInViewRange(it, x, y)) return true
}
return false
}
/** 指定位置([x],[y])是否在视图[view]的范围中 */
private fun isInViewRange(view: View, x: Int, y: Int): Boolean {
val leftTop = IntArray(2)
view.getLocationInWindow(leftTop)
val left = leftTop[0]
val top = leftTop[1]
val bottom = top + view.height
val right = left + view.width
return x in left..right && y in top..bottom
}
/** 隐藏输入法 */
private fun hideSoftInput() {
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManag
imm.hideSoftInputFromWindow(currentFocus?.windowToken, 0)
}
}
实现思路是对所有可获取焦点的视图进行遍历,判断触摸点是否在可见的 EditText 范围内,如果不是则隐藏输入法。
使用这种写法,软键盘不会在多个 EditText 之间切换焦点时重复关闭打开。