默認(rèn)情況下,點(diǎn)擊EditText會(huì)打開輸入法。項(xiàng)目中有個(gè)需求功能是點(diǎn)擊其他地方(除鍵盤外)可以關(guān)閉輸入法,第一時(shí)間想到的是,點(diǎn)擊其他View就收起輸入法,那么有個(gè)問(wèn)題,當(dāng)你View很多是時(shí)候,你都要對(duì)每個(gè)View注冊(cè)點(diǎn)擊事件,過(guò)于復(fù)雜。研究出一種方法,記錄一下怎么做的
點(diǎn)擊事件都會(huì)進(jìn)入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)
}
// 如果焦點(diǎn)不是EditText則忽略,這個(gè)發(fā)生在視圖剛繪制完,第一個(gè)焦點(diǎn)不在EditText上,和用戶用軌跡球選擇其他的焦點(diǎn)
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、首先判斷點(diǎn)擊事件是否為DOWN,之后再判斷是否收起鍵盤
2、isShouldHideKeyboard中需要處于當(dāng)前焦點(diǎn)的View和事件event
3、判斷當(dāng)前獲取焦點(diǎn)的View的類似是否為EditText,如果不是則不做處理,是的話再判斷
4、添加過(guò)濾的View,即點(diǎn)擊該View不作處理(可以在子Activity里面添加)
5、isEventInViewBound作用是判斷當(dāng)前的點(diǎn)擊是否在這個(gè)View外面,如果點(diǎn)擊不落在該View,則收起輸入法
6、v.getLocationInWindow(l)取到View的X,Y點(diǎn),之后取到View的四個(gè)點(diǎn),如果event的點(diǎn)擊不范圍不在View內(nèi),return true,輸入法收起,否則return false,不作處理
注:currentFocus是當(dāng)前獲取焦點(diǎn)的View,聚焦和點(diǎn)擊是不同的概念,可以理解為聚焦的View是光標(biāo)閃爍的View
關(guān)于hideSoftInput()
fun View.hideSoftInput() { // 關(guān)閉輸入法
(BaseApplication.appContext.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.apply {
hideSoftInputFromWindow(windowToken, 0)
}
this.clearFocus()
}
在Kotlin中可以添加擴(kuò)展方法,把你需要的操作放入擴(kuò)展方法里面,之后直接調(diào)去就好了