Search code examples
javaandroidandroid-softkeyboard

Hiding softkeyboard reliably


I have a application, and need to close the softkeyboard on a rather large amount of actions. For example, when clicking a button, when a new layout is drawn, on screen orientation change, when the controller tells the UI to, et cetera. I use the optionsMenuButton to flip view with a ViewFlipper, and obviously I want the keyboard to hide in the flipped view (there is no input field there).

I've tried these so far and tell why these aren't reliable:

This one didn't work because I have lots of editTexts, and other views. I need a more generic one, one that does not require a view as argument, if possible.

InputMethodManager imm = (InputMethodManager)getSystemService(
  Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);

This one does not work at all for me:

getWindow().setSoftInputMode(
  WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

This one works, but immediately pops the keyboard up again when the view is flipped.

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

This one works sometimes, but getCurrentFocus() returns null most of the time.

InputMethodManager inputManager = (InputMethodManager)            
Context.getSystemService(Context.INPUT_METHOD_SERVICE); 
inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(),      
InputMethodManager.HIDE_NOT_ALWAYS);

This one works only if the keyboard is shown:

getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);

This one does not work with the EditText like the first piece of code, but with the root Layout, which changes on orientation change and everytime the oncreate is called. I have different layout XML for landscape/portrait and normal/large. All the root Layouts have the ID root. This works nicely the first time, but after that, it doesn't work anymore.

InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(findViewById(R.id.root).getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);

Bottomline: I've tried hella lot of softkeyboard hiding methods, but none of them seems to work reliably. Is there any method for hiding the soft keyboard reliably?


Solution

  • Since you need an EditText to bring up the keyboard, find the particular one and use the first method you displayed to hide the keyboard:

    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);
    

    However, you will need that EditText. First, get all views:

    public static ArrayList<View> getAllViewsFromRoots(View...roots) {
        ArrayList<View> result = new ArrayList<View>();
        for (View root : roots) {
            getAllViews(result, root);
        }
        return result;
    }
    
    private static void getAllViews(ArrayList<View> allviews, View parent) {
        allviews.add(parent);
        if (parent instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup)parent;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                getAllViews(allviews, viewGroup.getChildAt(i));
            }
        }
    }
    

    Then, get an EditText which is visible.

    public static EditText getEditText(View root) {
        ArrayList<View> views = getAllViewsFromRoots(root);
        for (View view : views) {
            if (view instanceof EditText && view.getVisibility() == View.VISIBLE) {
                return (EditText) view;
            }
        }
        return null;
    }
    

    Call somewhere:

    Toolkit.getEditText(((ViewParent) findViewById(android.R.id.content)).getChildAt(0));
    

    with that, call the hiding method.