一、功能和亮点
- 点击焦点EditText外,拦截触摸事件且收起键盘;
- 点击焦点EditText外,正常下发触摸事件且收起键盘;
- 点击焦点EditText外,正常下发触摸事件但不收起键盘;
- 键盘弹出时,可正常进行滑动事件
- 50行以内代码量
- 一行代码调用,实现最低业务入侵
二、代码
class GestureDetectorHolder(val activity: Activity) {
var excludeViews = hashSetOf<View>()
private val detector: GestureDetector by lazy {
var isIntercept = false
object : GestureDetector(activity, object : GestureDetector.SimpleOnGestureListener() {
val outRect = Rect()
override fun onDown(e: MotionEvent): Boolean {
return activity.currentFocus is EditText && excludeViews.apply {
add(activity.currentFocus)
}.all {
outRect.apply {
it.getGlobalVisibleRect(this)
}.let { !it.contains(e.x.toInt(), e.y.toInt()) }
}.also {
isIntercept = it
}
}
override fun onSingleTapUp(e: MotionEvent): Boolean {
return isIntercept.apply {
(activity.currentFocus as? EditText)?.takeIf { this }?.apply {
closeInputMethodAndClearFocus()
}
}
}
override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
if (isIntercept) {
isIntercept = false
e2.action = ACTION_DOWN
e2.setLocation(e1.rawX, e1.rawY)
}
return false
}
}){
override fun onTouchEvent(ev: MotionEvent): Boolean {
return activity.currentFocus.let { if (it != null)WindowUtils.isInputVisible(it) else false } and super.onTouchEvent(ev)
}
}.also {
it.setIsLongpressEnabled(false)
}
}
fun dispatchMotionEvent(event: MotionEvent, vararg views: View?):Boolean {
return !detector.onTouchEvent(event) || Rect().let {rect->
views.filterNotNull().any {
rect.setEmpty()
it.getGlobalVisibleRect(rect)
rect.contains(event.x.toInt(), event.y.toInt())
}
}
}
}
三、使用方法
重写Activity.dispatchTouchEvent(ev: MotionEvent): Boolean方法,由GestureDetectorHolder.dispatchMotionEvent(ev: MotionEvent, vararg views: View?): Boolean代理实现
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
return GestureDetectorHolder(this).apply {
excludeViews = hashSetOf(editAddress, editNotes, editContent)
}.dispatchMotionEvent(ev, iftActionLeft, iftActionRight) && super.dispatchTouchEvent(ev)
}
excludeViews:gestureDetectorHolder将忽略这些View,当键盘弹出时,点击这些View正常下发触摸事件,且不收起键盘
dispatchMotionEvent(event: MotionEvent, vararg views: View?):
views:gestureDetectorHolder将特殊处理这些View,当键盘弹出时,点击这些View正常下发触摸事件,但收起键盘
其他区域:拦截触摸事件,且收起键盘
四、EditText失焦隐藏光标
fun View.openInputMethod() {
if (!isFocused) {
isFocusable = true
isFocusableInTouchMode = true
requestFocus()
(this as? EditText)?.isCursorVisible = true
postDelayed({
(context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager).showSoftInput(this, SHOW_FORCED)
}, 100)
}
}
fun View.closeInputMethod() {
(context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(windowToken, 0)
}
fun EditText.closeInputMethodAndClearFocus() {
closeInputMethod().apply {
isCursorVisible = false
isFocusable = false
isFocusableInTouchMode = false
clearFocus()
}
}