You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EditText获焦时点击外部隐藏软键盘失效问题求助

解决ScrollView嵌套下点击外部隐藏软键盘失效的问题

问题原因

当布局嵌套ScrollView时,ScrollView会拦截并消费触摸事件,导致Activity的onTouchEvent无法接收到点击事件,因此原有逻辑失效。

可行解决方案

方案1:自定义ScrollView处理触摸事件

重写ScrollView的onTouchEvent方法,在触摸事件中判断点击区域是否在EditText外,若是则隐藏软键盘:

class CustomScrollView(context: Context, attrs: AttributeSet?) : ScrollView(context, attrs) {
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_DOWN) {
            val activity = context as Activity
            val currentFocus = activity.currentFocus
            if (currentFocus is EditText) {
                val outRect = Rect()
                currentFocus.getGlobalVisibleRect(outRect)
                // 判断点击位置是否在EditText区域外
                if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
                    currentFocus.clearFocus()
                    val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                    imm.hideSoftInputFromWindow(currentFocus.windowToken, 0)
                }
            }
        }
        // 保留ScrollView的原生滚动逻辑
        return super.onTouchEvent(event)
    }
}

将布局中的原生ScrollView替换为自定义的CustomScrollView即可。

方案2:在Activity的dispatchTouchEvent中处理

dispatchTouchEvent是触摸事件分发的起点,不受子View拦截影响,直接在这里判断处理:

override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
    if (ev.action == MotionEvent.ACTION_DOWN) {
        val currentFocus = currentFocus
        if (currentFocus is EditText) {
            val outRect = Rect()
            currentFocus.getGlobalVisibleRect(outRect)
            if (!outRect.contains(ev.rawX.toInt(), ev.rawY.toInt())) {
                currentFocus.clearFocus()
                val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                imm.hideSoftInputFromWindow(currentFocus.windowToken, 0)
            }
        }
    }
    return super.dispatchTouchEvent(ev)
}

替换原有Activity中重写的onTouchEvent方法即可,无需修改布局结构。

方案3:给ScrollView设置触摸监听器

在Fragment中给ScrollView添加OnTouchListener,逻辑与自定义ScrollView一致:

scrollView.setOnTouchListener { v, event ->
    if (event.action == MotionEvent.ACTION_DOWN) {
        val activity = requireActivity()
        val currentFocus = activity.currentFocus
        if (currentFocus is EditText) {
            val outRect = Rect()
            currentFocus.getGlobalVisibleRect(outRect)
            if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
                currentFocus.clearFocus()
                val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                imm.hideSoftInputFromWindow(currentFocus.windowToken, 0)
            }
        }
    }
    // 传递事件给ScrollView,保证滚动功能正常
    v.onTouchEvent(event)
}

内容的提问来源于stack exchange,提问作者wish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 07:55:40