stealthjong
stealthjong

Reputation: 11093

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?

Upvotes: 15

Views: 14003

Answers (6)

Matheus Sant Ana
Matheus Sant Ana

Reputation: 690

Try this:

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

Upvotes: 0

Nihal Desai
Nihal Desai

Reputation: 33

kotlin. Put this on common BaseActivity. just call hideKeyboard() method anywhere in your activity similar apply for Fragment.

open class BaseActivity : AppCompatActivity() {

fun Fragment.hideKeyboard() {
    view?.let { activity?.hideKeyboard(it) }
}

fun Context.hideKeyboard(view: View) {
    val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}

}

Upvotes: 1

MC Emperor
MC Emperor

Reputation: 22997

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.

Upvotes: 8

FDIM
FDIM

Reputation: 1989

Only this solution worked for me:

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

I had a dialog with input field, hiding the dialog didnt hide the keyboard on tablet.

Upvotes: 0

Arda Yigithan Orhan
Arda Yigithan Orhan

Reputation: 1052

I think if you handle the null case of getCurrentFocus(), you're good to go. I use the method below and it works like a charm!

     /* Hide Keyboard */
    public static void hideKeyboard(Activity activity){
        InputMethodManager inputMethodManager = (InputMethodManager)activity
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        View focus = activity.getCurrentFocus();
        if(focus != null)
            inputMethodManager.hideSoftInputFromWindow(focus.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }

Upvotes: 9

ThePCWizard
ThePCWizard

Reputation: 3348

This one works for me always:

InputMethodManager im = (InputMethodManager) getSystemService(MyActivity.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);

Upvotes: 4

Related Questions