默认情况下,点击EditText会打开输入法。项目中有个需求功能是点击其他地方(除键盘外)可以关闭输入法,第一时间想到的是,点击其他View就收起输入法,那么有个问题,当你View很多是时候,你都要对每个View注册点击事件,过于复杂。研究出一种方法,记录一下怎么做的
点击事件都会进入Activity的dispatchTouchEvent里面,所以可以在Activity的基类里面做处理
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
if (ev.action == MotionEvent.ACTION_DOWN) {
if (isShouldHideKeyboard(currentFocus, ev)) {
currentFocus?.hideSoftInput()
}
}
return super.dispatchTouchEvent(ev)
}
open fun isShouldHideKeyboard(v: View?, event: MotionEvent): Boolean {
if (v is EditText) {
var result = true
needFilterHideKeyboardView().forEach {
result = result && isEventInViewBound(it, event)
}
return result && isEventInViewBound(v, event)
}
// 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点
return false
}
private fun isEventInViewBound(v: View, event: MotionEvent): Boolean {
val l = intArrayOf(0, 0)
v.getLocationInWindow(l)
val left = l[0]
val top = l[1]
val bottom = top + v.height
val right = left + v.width
return event.x <= left || event.x >= right || event.y <= top || event.y >= bottom
}
open fun needFilterHideKeyboardView(): List<View> = emptyList()
分析:
1、首先判断点击事件是否为DOWN,之后再判断是否收起键盘
2、isShouldHideKeyboard中需要处于当前焦点的View和事件event
3、判断当前获取焦点的View的类似是否为EditText,如果不是则不做处理,是的话再判断
4、添加过滤的View,即点击该View不作处理(可以在子Activity里面添加)
5、isEventInViewBound作用是判断当前的点击是否在这个View外面,如果点击不落在该View,则收起输入法
6、v.getLocationInWindow(l)取到View的X,Y点,之后取到View的四个点,如果event的点击不范围不在View内,return true,输入法收起,否则return false,不作处理
注:currentFocus是当前获取焦点的View,聚焦和点击是不同的概念,可以理解为聚焦的View是光标闪烁的View
关于hideSoftInput()
fun View.hideSoftInput() { // 关闭输入法
(BaseApplication.appContext.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.apply {
hideSoftInputFromWindow(windowToken, 0)
}
this.clearFocus()
}
在Kotlin中可以添加扩展方法,把你需要的操作放入扩展方法里面,之后直接调去就好了
网友评论