简体   繁体   中英

How to make the soft keyboard hide when clicked outside of the focused EditText BUT not if another EditText is clicked?

I want the focused EditText to lose its focus and the soft keyboard to hide when clicked outside the EditText box BUT only when another EditText is not clicked, so these are the scenarios:

  1. The EditText is focused, another EditText is clicked - lose first EditText's focus BUT don't hide the soft keyboard as another EditText's focus is requested.
  2. The EditText is focused, some other part of the Layout is clicked - lose EditText's focus AND hide the soft keyboard as none of the EditTexts is focused.

Right now my implementation looks like this.

FocusChangeListeners:

    edittext1.setOnFocusChangeListener(object : View.OnFocusChangeListener {
        override fun onFocusChange(v: View?, hasFocus: Boolean) {
            if (!hasFocus) {
                edittext1.clearFocus()
            }
        }
    })

    edittext2.setOnFocusChangeListener(object : View.OnFocusChangeListener {
        override fun onFocusChange(v: View?, hasFocus: Boolean) {
            if (!hasFocus) {
                edittext2.clearFocus()
            }
        }
    })

DispatchTouchEvent:

override fun dispatchTouchEvent(event: MotionEvent): Boolean {
    if (event.action == MotionEvent.ACTION_DOWN) {
        val v = currentFocus
        if (v is EditText) {
            val outRect = Rect()
            v.getGlobalVisibleRect(outRect)
            if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
                v.clearFocus()
                // if not another EditText clicked, hide keyboard
                val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0)
            }
        }
    }
    return super.dispatchTouchEvent(event)
}

The problem I have is that it is only checked if the click was outside of the EditText's box so the soft keyboard is being hidden even if the other EditText is focused with the click. What is the solution to overcome this issue?

I was able to come up with an answer based on other implementations found. It's not very elegant but it does the job.

override fun dispatchTouchEvent(event: MotionEvent): Boolean {
    if (event.action == MotionEvent.ACTION_DOWN) {
        val v = currentFocus
        if (v is EditText) {
            val outRect = Rect()
            v.getGlobalVisibleRect(outRect)
            val x = event.rawX.toInt()
            val y = event.rawY.toInt()
            if (!outRect.contains(x, y)) {
                v.clearFocus()
                val et1: EditText? = findViewById(R.id.edittext1)
                val et2: EditText? = findViewById(R.id.edittext2)
                val rect1 = Rect()
                val rect2 = Rect()
                val location1 = IntArray(2)
                val location2 = IntArray(2)
                et1!!.getLocationOnScreen(location1)
                rect1.left = location1[0]
                rect1.top = location1[1]
                rect1.right = location1[0] + et1.width
                rect1.bottom = location1[1] + et1.height
                et2!!.getLocationOnScreen(location2)
                rect2.left = location2[0]
                rect2.top = location2[1]
                rect2.right = location2[0] + et2.width
                rect2.bottom = location2[1] + et2.height
                if ((!rect1.contains(x, y)) && (!rect2.contains(x, y))) {
                    val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
                    imm.hideSoftInputFromWindow(v.getWindowToken(), 0)
                }
            }
        }
    }
    return super.dispatchTouchEvent(event)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM