How to hide soft keyboard on android after clicking outside EditText?

前端 未结 30 1729
醉话见心
醉话见心 2020-11-22 11:46

Ok everyone knows that to hide a keyboard you need to implement:

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hi         


        
30条回答
  •  有刺的猬
    2020-11-22 12:10

    Here's another variation on fje's answer that addresses the issues raised by sosite.

    The idea here is to handle both the down and the up actions in the Activity's dispatchTouchEvent method. On the down action, we make note of the currently focused view (if any) and whether the touch was inside it, saving both those bits of info for later.

    On the up action, we first dispatch, to allow another view to potentially take focus. If after that, the currently focused view is the originally focused view, and the down touch was inside that view, then we leave the keyboard open.

    If the currently focused view is different than the originally focused view and it's an EditText, then we also leave the keyboard open.

    Otherwise we close it.

    So, to sum up, this works as follows:

    • when touching inside a currently focused EditText, the keyboard stays open
    • when moving from a focused EditText to another EditText, the keyboard stays open (doesn't close/reopen)
    • when touching anywhere outside a currently focused EditText that is not another EditText, the keyboard closes
    • when long-pressing in an EditText to bring up the contextual action bar (with the cut/copy/paste buttons), the keyboard stays open, even though the UP action took place outside the focused EditText (which moved down to make room for the CAB). Note, though, that when you tap on a button in the CAB, it will close the keyboard. That may or may not be desirable; if you want to cut/copy from one field and paste to another, it would be. If you want to paste back into the same EditText, it would not be.
    • when the focused EditText is at the bottom of the screen and you long-click on some text to select it, the EditText keeps focus and therefore the keyboard opens like you want, because we do the "touch is within view bounds" check on the down action, not the up action.

      private View focusedViewOnActionDown;
      private boolean touchWasInsideFocusedView;
      
      
      @Override
      public boolean dispatchTouchEvent(MotionEvent ev) {
          switch (ev.getAction()) {
              case MotionEvent.ACTION_DOWN:
                  focusedViewOnActionDown = getCurrentFocus();
                  if (focusedViewOnActionDown != null) {
                      final Rect rect = new Rect();
                      final int[] coordinates = new int[2];
      
                      focusedViewOnActionDown.getLocationOnScreen(coordinates);
      
                      rect.set(coordinates[0], coordinates[1],
                              coordinates[0] + focusedViewOnActionDown.getWidth(),
                              coordinates[1] + focusedViewOnActionDown.getHeight());
      
                      final int x = (int) ev.getX();
                      final int y = (int) ev.getY();
      
                      touchWasInsideFocusedView = rect.contains(x, y);
                  }
                  break;
      
              case MotionEvent.ACTION_UP:
      
                  if (focusedViewOnActionDown != null) {
                      // dispatch to allow new view to (potentially) take focus
                      final boolean consumed = super.dispatchTouchEvent(ev);
      
                      final View currentFocus = getCurrentFocus();
      
                      // if the focus is still on the original view and the touch was inside that view,
                      // leave the keyboard open.  Otherwise, if the focus is now on another view and that view
                      // is an EditText, also leave the keyboard open.
                      if (currentFocus.equals(focusedViewOnActionDown)) {
                          if (touchWasInsideFocusedView) {
                              return consumed;
                          }
                      } else if (currentFocus instanceof EditText) {
                          return consumed;
                      }
      
                      // the touch was outside the originally focused view and not inside another EditText,
                      // so close the keyboard
                      InputMethodManager inputMethodManager =
                              (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                      inputMethodManager.hideSoftInputFromWindow(
                          focusedViewOnActionDown.getWindowToken(), 0);
                      focusedViewOnActionDown.clearFocus();
      
                      return consumed;
                  }
                  break;
          }
      
          return super.dispatchTouchEvent(ev);
      }
      

提交回复
热议问题