Android EditText打开输入法后,点击任意位置收起输入法

默认情况下,点击EditText会打开输入法。项目中有个需求功能是点击其他地方(除键盘外)可以关闭输入法,第一时间想到的是,点击其他View就收起输入法,那么有个问题,当你View很多是时候,你都要对每个View注册点击事件,过于复杂。研究出一种方法,记录一下怎么做的

点击事件都会进入Activity的dispatchTouchEvent里面,所以可以在Activity的基类里面做处理

  override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
    if (ev.action == MotionEvent.ACTION_DOWN) {
      if (isShouldHideKeyboard(currentFocus, ev)) {
        currentFocus?.hideSoftInput()
      }
    }
    return super.dispatchTouchEvent(ev)
  }

  open fun isShouldHideKeyboard(v: View?, event: MotionEvent): Boolean {
    if (v is EditText) {
      var result = true
      needFilterHideKeyboardView().forEach {
        result = result && isEventInViewBound(it, event)
      }
      return result && isEventInViewBound(v, event)
    }
    // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点
    return false
  }

  private fun isEventInViewBound(v: View, event: MotionEvent): Boolean {
    val l = intArrayOf(0, 0)
    v.getLocationInWindow(l)
    val left = l[0]
    val top = l[1]
    val bottom = top + v.height
    val right = left + v.width
    return event.x <= left || event.x >= right || event.y <= top || event.y >= bottom
  }

  open fun needFilterHideKeyboardView(): List = emptyList()

分析:
1、首先判断点击事件是否为DOWN,之后再判断是否收起键盘
2、isShouldHideKeyboard中需要处于当前焦点的View和事件event
3、判断当前获取焦点的View的类似是否为EditText,如果不是则不做处理,是的话再判断
4、添加过滤的View,即点击该View不作处理(可以在子Activity里面添加)
5、isEventInViewBound作用是判断当前的点击是否在这个View外面,如果点击不落在该View,则收起输入法
6、v.getLocationInWindow(l)取到View的X,Y点,之后取到View的四个点,如果event的点击不范围不在View内,return true,输入法收起,否则return false,不作处理
注:currentFocus是当前获取焦点的View,聚焦和点击是不同的概念,可以理解为聚焦的View是光标闪烁的View

关于hideSoftInput()

fun View.hideSoftInput() { // 关闭输入法
  (BaseApplication.appContext.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.apply {
    hideSoftInputFromWindow(windowToken, 0)
  }
  this.clearFocus()
}

在Kotlin中可以添加扩展方法,把你需要的操作放入扩展方法里面,之后直接调去就好了

你可能感兴趣的:(Android EditText打开输入法后,点击任意位置收起输入法)