1

I have a form-like dialog. The soft keyboard opens when the user clicks an EditText. And then it will not go away.

How can I close the keyboard when the user moves on from an EditText to the next section, clicking a Spinner or Button or RadioButton?

Kaitlyn Hanrahan
  • 759
  • 6
  • 22
  • `How to close the Android Soft Keyboard` i feel like your title is misleading, as this has been asked and answered already, so this just feels like a duplicate, but your post feels to be more specific than that, perhaps you can/should rework this post to be specifically about closing the keyboard in a specific situation, otherwise it might be more useful to just write this as an answer on the post you've already linked – a_local_nobody May 30 '22 at 15:06
  • also, this is just my advice on how to get the most for the work that you've done, don't take this in a negative way, if you want to keep it here as it is, feel free to flag my comments to have them removed – a_local_nobody May 30 '22 at 15:13

1 Answers1

2

How to close the keyboard

The code to close the soft keyboard is this:

InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);

You can turn this to a utility function as so, and then call it statically throughout your app: (taken from this very nice answer: https://stackoverflow.com/a/17789187)

// Close keyboard. Wont work if an EditText has focus.
public static void hideKeyboard(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    //Find the currently focused view, so we can grab the correct window token from it.
    View view = activity.getCurrentFocus();
    //If no view currently has focus, create a new one, just so we can grab a window token from it
    if (view == null) {
        view = new View(activity);
    }
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Where to close the keyboard

On loss of focus? No.

The logical place to call the code to close the soft keyboard would be an onFocus listener attached to the EditText. And then close the keyboard when the EditText loses focus

However, a EditText does not give up its focus for buttons or spinners or radio buttons. Those other UI elements need to explicitly ask for focus with requestFocusFromTouch().

It will not work to have the other UI elements call requestFocusFromTouch() on click and then the EditText close the keyboard on the loss of focus. When the EditText has focus the keyboard will not close. When the EditText does not have focus, it no longer has the authority to close the keyboard. Ironic, I know.

Only the currently focused View can close the keyboard.

Giving focus to a UI element that doesn't need a keyboard, won't close the keyboard; it simply updates it. For example, if the EditText has a numerical keyboard, after clicking a button that requests focus, there will be an alphanumeric keyboard.

On button touch? Yes.

You can add a touch listener to other UI elements and even Layouts. For example, a Spinner could try to close the keyboard:

// Close keyboard on touch. Wont work if Edit text has focus.
mSpinner.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                InputMethodManager imm=(InputMethodManager)getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
                return false;
            }
        }) ;

However, the EditText probably still has focus and will not let you close that keyboard.

The newly clicked button/spinner/radio/etc needs to both request focus and close the keyboard. As a static util function it looks like this:

// add touch listener to given view. On touch, request focus, then close keyboard
public static void hideKeyboardOnTouch(View view, Activity activity){
    Context app = activity.getApplicationContext();
    view.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            v.requestFocusFromTouch();
            InputMethodManager imm=(InputMethodManager)app.getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            return false;
        }
    }) ;
}

And for all your other buttons, radio buttons, spinners, etc. When you set them you also add this. For example:

        radioA = view.findViewById(R.id.radio_a);
        radioA.setChecked(myBooleanValueHere);
        Utils.hideKeyboardOnTouch(radioA, getActivity()); // <-- close keyboard on touch
        radioA.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // whatever should happen when this radio button is selected
            }
        });

Note, my example is in a Dialog. If in an Activity, you would use this rather than getActivity().

You could also have the buttons/spinners/etc request focus and then close the keyboard on their onClick functions. I chose this method because it can be used very consistently for Spinners, layouts, and anything else where I may not have an onClick defined.

Hope this is helpful! And I can save someone from finding all these things out the way I did :))

Kaitlyn Hanrahan
  • 759
  • 6
  • 22