Search code examples
androidkotlinandroid-layoutscrollview

How do I hide the soft keyboard?


While foucusing edittext, I would like to hide the soft keyboard when tapping outside the range.

MainActivity.kt

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if (currentFocus != null) {
            val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

            inputMethodManager.hideSoftInputFromWindow(
                // container is ConstraintLayout
                binding.container.windowToken,
                InputMethodManager.HIDE_NOT_ALWAYS
            )
        }
        return false
    }

Input Method Manager is written in MainActivity

in a xml

<ConstraintLayout>
    <ScrollView>
        <LinearLayout>

        </LinearLayout>
    </ScrollView>
</ConstraintLayout>

When I create this layout, the keyboard does not hide when I tap outside the range How can I hide the keyboard?

If I write only ConstraintLayout it works but no scrolling

xxFragment.kt

scrollView.setOnClickListener {
    val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.hideSoftInputFromWindow(binding.scrollView.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
}

I tried the above code and it failed


Solution

  • You need to override dispatchTouchEvent() method of Activity.

    Just write this code in your activity and it will hide soft keyboard as soon as you touch outside EditText. No need to call any function anywhere. It will work on all the fragments of the activity.

    /**
     * Hide Keyboard when tapped outside editText
     */
    private var pressTime: Long = 0L
    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        val ret = super.dispatchTouchEvent(ev)
        ev?.let { event ->
            if (ev.action == MotionEvent.ACTION_DOWN) {
                pressTime = System.currentTimeMillis()
            } else if (event.action == MotionEvent.ACTION_UP) {
                val releaseTime = System.currentTimeMillis()
                if (releaseTime - pressTime < 100) {
                    currentFocus?.let { view ->
                        if (view is EditText) {
                            val touchCoordinates = IntArray(2)
                            view.getLocationOnScreen(touchCoordinates)
                            val x: Float = event.rawX + view.getLeft() - touchCoordinates[0]
                            val y: Float = event.rawY + view.getTop() - touchCoordinates[1]
                            //If the touch position is outside the EditText then we hide the keyboard
                            if (x < view.getLeft() || x >= view.getRight() || y < view.getTop() || y > view.getBottom()) {
                                val imm =
                                    getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                                imm.hideSoftInputFromWindow(view.windowToken, 0)
                                view.clearFocus()
                            }
                        }
                    }
                }
            }
        }
        return ret
    }