Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 831
stealthjong Avatar asked Oct 23 '12 14:10

stealthjong


People also ask

Is there any way to dismiss the keyboard programmatically?

Hiding the Soft Keyboard Programmatically You can force Android to hide the virtual keyboard using the InputMethodManager, calling hideSoftInputFromWindow, passing in the token of the window containing your edit field. This will force the keyboard to be hidden in all situations.


4 Answers

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);
    }
like image 80
Arda Yigithan Orhan Avatar answered Nov 08 '22 18:11

Arda Yigithan Orhan


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.

like image 22
MC Emperor Avatar answered Nov 08 '22 18:11

MC Emperor


This one works for me always:

InputMethodManager im = (InputMethodManager) getSystemService(MyActivity.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
like image 4
ThePCWizard Avatar answered Nov 08 '22 17:11

ThePCWizard


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)
}

}
like image 1
Nihal Desai Avatar answered Nov 08 '22 16:11

Nihal Desai