Android點擊EditText輸入框外收起鍵盤,不影響滑動事件和功能按鈕點擊事件

一、功能和亮點

  1. 點擊焦點EditText外,攔截觸摸事件且收起鍵盤;
  2. 點擊焦點EditText外,正常下發(fā)觸摸事件且收起鍵盤;
  3. 點擊焦點EditText外,正常下發(fā)觸摸事件但不收起鍵盤;
  4. 鍵盤彈出時,可正常進行滑動事件
  5. 50行以內(nèi)代碼量
  6. 一行代碼調(diào)用,實現(xiàn)最低業(yè)務入侵

二、代碼

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代理實現(xiàn)

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正常下發(fā)觸摸事件,且不收起鍵盤

dispatchMotionEvent(event: MotionEvent, vararg views: View?):

views:gestureDetectorHolder將特殊處理這些View,當鍵盤彈出時,點擊這些View正常下發(fā)觸摸事件,但收起鍵盤

其他區(qū)域:攔截觸摸事件,且收起鍵盤

四、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()
    }
}
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容