android点击EditText外区域收起键盘
16lz
2021-01-26
在日常开发中,Activity中可能有比较复杂的布局,比如嵌套很多Fragment,所以针对该需求,通常的做法为放到Activity中统一处理。
常规思路为在dispatchTouchEvent中不拦截MotionEvent,但是会根据event是否落在EditText中做相应的处理,具体做法为
@Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { View v = getCurrentFocus(); if (isShouldHideInput(v, ev)) { hideInputMethod(this, v); } } return super.dispatchTouchEvent(ev); } private boolean isShouldHideInput(View v, MotionEvent event) { if (v != null && (v instanceof EditText)) { int[] leftTop = {0, 0}; v.getLocationInWindow(leftTop); int left = leftTop[0], top = leftTop[1], bottom = top + v.getHeight(), right = left + v.getWidth(); if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) { return false; } else { return true; } } return false; } private Boolean hideInputMethod(Context context, View v) { v.clearFocus(); InputMethodManager imm = (InputMethodManager)context .getSystemService(Context.INPUT_METHOD_SERVICE); if (imm != null) { imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } return false; }
在Down事件时如果event不在当前获取焦点的EditText中,则收起键盘,另外清除焦点,注意EditText的parent需要设置如下属性保证可以获取焦点,一般直接设置在activity的顶层布局中
android:focusable="trur"android:focusableInTouchMode="trur"
如上处理后会发现用户在EditText间切换焦点时不正常,键盘会出现先收起再弹出,我们要做的是能判断MotionEvent消费后是否由其它EditText获取到了焦点,如果是的话则不收起键盘。
当用户点击其它EditText时,只有Up事件发生时才会完成focus切换,所以做法有两种,第一种比较简单,延时200ms再判断就可以覆盖绝大部分场景,不过会出现用户按住其它EditText时键盘收起等情况。
private boolean hideInputMethod(Context context, View v) { // 延时100ms判断焦点是否还在edittext,不在的话则隐藏键盘 mHandler.postDelayed(() -> { View current = getCurrentFocus(); if (current == v) { v.clearFocus(); InputMethodManager imm = (InputMethodManager)context .getSystemService(Context.INPUT_METHOD_SERVICE); if (imm != null) { imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } } }, 200); return false; }
另外一个更好的方法是在dispatchTouchEvent中监听焦点的变化,如果down和up时焦点无变化,则认为需要收起键盘,与上面类似。具体代码如下
boolean pendingCollapseKeyword = false; View focusedView; // 点击非输入框位置优先隐藏软键盘 @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { pendingCollapseKeyword = isShouldHideInput(ev); if (pendingCollapseKeyword) focusedView = getCurrentFocus(); } else if (ev.getAction() == MotionEvent.ACTION_UP) { if (pendingCollapseKeyword) { hideInputMethod(this); } } return super.dispatchTouchEvent(ev); } private boolean isShouldHideInput(MotionEvent event) { View v = getCurrentFocus(); if (v instanceof EditText) { int[] location = {0, 0}; v.getLocationInWindow(location); return event.getX() < location[0] || event.getX() > location[0] + v.getWidth() || event.getY() < location[1] || event.getY() > location[1] + v.getHeight(); } return false; } // 抬起手指时如果焦点还在原来的EditText则收起键盘 private void hideInputMethod(Context context) { View v = getCurrentFocus(); if (v == focusedView) { focusedView.clearFocus(); InputMethodManager imm = (InputMethodManager)context .getSystemService(Context.INPUT_METHOD_SERVICE); if (imm != null) { imm.hideSoftInputFromWindow(focusedView.getWindowToken(), 0); } } }
如上同时兼顾了两个需求
- 点击EditText外收起键盘
- 点击其它EditText保持键盘状态不变
更多相关文章
- TextView文字横向自动滚动(跑马灯)
- RN中解决键盘问题- 将tab navigation顶起来
- 使用jQuery Mobile的注意事项
- android EditText属性详解
- Android(安卓)- 判断当前网络环境、隐藏软键盘、动态监测及获取
- Android软键盘一些处理
- android 软件盘相关
- 关于Android中Animation的停止
- Android(安卓)软键盘盖住输入框或者布局的解决办法