Close/hide the Android Soft Keyboard


I have an EditText and a Button in my layout.

After writing in the edit field and clicking on the Button, I want to hide the virtual keyboard. I assume that there's a simple, one or two-liner code to make this happen.

Where can I find an example of it?


Answers


You can force Android to hide the virtual keyboard using the InputMethodManager, calling hideSoftInputFromWindow, passing in the token of the window containing your focused view.

// Check if no view has focus:
View view = this.getCurrentFocus();
if (view != null) {  
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

This will force the keyboard to be hidden in all situations. In some cases you will want to pass in InputMethodManager.HIDE_IMPLICIT_ONLY as the second parameter to ensure you only hide the keyboard when the user didn't explicitly force it to appear (by holding down menu).




To help clarify this madness, I'd like to begin by apologizing on behalf of all Android users for Google's downright ridiculous treatment of the soft keyboard. The reason there are so many answers, each different, for the same simple question is because this API, like many others in Android, is horribly designed. I can think of no polite way to state it.

I want to hide the keyboard. I expect to provide Android with the following statement: Keyboard.hide(). The end. Thank you very much. But Android has a problem. You must use the InputMethodManager to hide the keyboard. OK, fine, this is Android's API to the keyboard. BUT! You are required to have a Context in order to get access to the IMM. Now we have a problem. I may want to hide the keyboard from a static or utility class that has no use or need for any Context. or And FAR worse, the IMM requires that you specify what View (or even worse, what Window) you want to hide the keyboard FROM.

This is what makes hiding the keyboard so challenging. Dear Google: When I'm looking up the recipe for a cake, there is no RecipeProvider on Earth that would refuse to provide me with the recipe unless I first answer WHO the cake will be eaten by AND where it will be eaten!!

This sad story ends with the ugly truth: to hide the Android keyboard, you will be required to provide 2 forms of identification: a Context and either a View or a Window.

I have created a static utility method which can do the job VERY solidly, provided you call it from an Activity.

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

Be aware that this utility method ONLY works when called from an Activity! The above method calls getCurrentFocus of the target Activity to fetch the proper window token.

But suppose you want to hide the keyboard from an EditText hosted in a DialogFragment? You can't use the method above for that:

hideKeyboard(getActivity()); //won't work

This won't work because you'll be passing a reference to the Fragment's host Activity, which will have no focused control while the Fragment is shown! Wow! So, for hiding the keyboard from fragments, I resort to the lower-level, more common, and uglier:

public static void hideKeyboardFrom(Context context, View view) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Below is some additional information gleaned from more time wasted chasing this solution:

About windowSoftInputMode

There's yet another point of contention to be aware of. By default, Android will automatically assign initial focus to the first EditText or focusable control in your Activity. It naturally follows that the InputMethod (typically the soft keyboard) will respond to the focus event by showing itself. The windowSoftInputMode attribute in AndroidManifest.xml, when set to stateAlwaysHidden, instructs the keyboard to ignore this automatically-assigned initial focus.

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

Almost unbelievably, it appears to do nothing to prevent the keyboard from opening when you touch the control (unless focusable="false" and/or focusableInTouchMode="false" are assigned to the control). Apparently, the windowSoftInputMode setting applies only to automatic focus events, not to focus events triggered from touch events.

Therefore, stateAlwaysHidden is VERY poorly named indeed. It should perhaps be called ignoreInitialFocus instead.

Hope this helps.


UPDATE: More ways to get a window token

If there is no focused view (e.g. can happen if you just changed fragments), there are other views that will supply a useful window token.

These are alternatives for the above code if (view == null) view = new View(activity); These don't refer explicitly to your activity.

Inside a fragment class:

view = getView().getRootView().getWindowToken();

Given a fragment fragment as a parameter:

view = fragment.getView().getRootView().getWindowToken();

Starting from your content body:

view = findViewById(android.R.id.content).getRootView().getWindowToken();

UPDATE 2: Clear focus to avoid showing keyboard again if you open the app from the background

Add this line to the end of the method:

view.clearFocus();




Also useful for hiding the soft-keyboard is:

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

This can be used to suppress the soft-keyboard until the user actually touches the editText View.




Programmatically Hide/Show Android Soft Keyboard

Adding this to your code android:focusableInTouchMode="true" will make sure that your keypad doesn't appear on startup for your edittext box. You want to add this line to your linear layout that contains the EditTextBox. You should be able to play with this to solve both your problems. I have tested this. Simple solution.

ie: In your app_list_view.xml file

<LinearLayout 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" 
    android:focusableInTouchMode="true">
    <EditText 
        android:id="@+id/filter_edittext"       
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:hint="Search" 
        android:inputType="text" 
        android:maxLines="1"/>
    <ListView 
        android:id="@id/android:list" 
        android:layout_height="fill_parent"
        android:layout_weight="1.0" 
        android:layout_width="fill_parent" 
        android:focusable="true" 
        android:descendantFocusability="beforeDescendants"/>
</LinearLayout> 

------------------ EDIT: To Make keyboard appear on startup -----------------------

This is to make they Keyboard appear on the username edittextbox on startup. All I've done is added an empty Scrollview to the bottom of the .xml file, this puts the first edittext into focus and pops up the keyboard. I admit this is a hack, but I am assuming you just want this to work. I've tested it, and it works fine.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:paddingLeft="20dip"  
    android:paddingRight="20dip">
    <EditText 
        android:id="@+id/userName" 
        android:singleLine="true" 
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content" 
        android:hint="Username"  
        android:imeOptions="actionDone" 
        android:inputType="text"
        android:maxLines="1"
       />
    <EditText 
        android:id="@+id/password" 
        android:password="true" 
        android:singleLine="true"  
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:hint="Password" />
    <ScrollView
        android:id="@+id/ScrollView01"  
        android:layout_height="fill_parent"   
        android:layout_width="fill_parent"> 
    </ScrollView>
</LinearLayout>

If you are looking for a more eloquent solution, I've found this question which might help you out, it is not as simple as the solution above but probably a better solution. I haven't tested it but it apparently works. I think it is similar to the solution you've tried which didn't work for you though.

Hope this is what you are looking for.

Cheers!




UPDATE 2

@Override
    protected void onResume() {
        super.onResume();
        mUserNameEdit.requestFocus();

        mUserNameEdit.postDelayed(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                InputMethodManager keyboard = (InputMethodManager)
                getSystemService(Context.INPUT_METHOD_SERVICE);
                keyboard.showSoftInput(mUserNameEdit, 0);
            }
        },200); //use 300 to make it run when coming back from lock screen
    }

I tried very hard and found out a solution ... whenever a new activity starts then keyboard cant open but we can use Runnable in onResume and it is working fine so please try this code and check...

UPDATE 1

add this line in your AppLogin.java

mUserNameEdit.requestFocus();

and this line in your AppList.java

listview.requestFocus()'

after this check your application if it is not working then add this line in your AndroidManifest.xml file

<activity android:name=".AppLogin" android:configChanges="keyboardHidden|orientation"></activity>
<activity android:name=".AppList" android:configChanges="keyboard|orientation"></activity>

ORIGINAL ANSWER

 InputMethodManager imm = (InputMethodManager)this.getSystemService(Service.INPUT_METHOD_SERVICE);

for hide keyboard

 imm.hideSoftInputFromWindow(ed.getWindowToken(), 0); 

for show keyboard

 imm.showSoftInput(ed, 0);

for focus on EditText

 ed.requestFocus();

where ed is EditText




Try this code,

For Showing Softkeyboard -

InputMethodManager imm = (InputMethodManager)
                                 getSystemService(Context.INPUT_METHOD_SERVICE);
if(imm != null){
        imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
    }

For Hiding SoftKeyboard -

InputMethodManager imm = (InputMethodManager)
                                  getSystemService(Context.INPUT_METHOD_SERVICE);
if(imm != null){
        imm.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);
    }

Hope this helps.




How to force keyboard to show/hide?

This should work

public class KeyBoard {

    public static void toggle(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        if (imm.isActive()){
            imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); // hide
        } else {
            imm.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY); // show
        }
    }//end method
}//end class



this link is clear about hiding the soft keyboard. to show it you can use a hack - create an EditText anywhere in your layout, layout_width and layout_height=0dip, and in onCreate do

yourEditText.requestFocus();



Prevent softkeyboard dismiss on the android back button press

create one custom EditText like follow with one interface:

public class CustomEditText extends EditText {


    public void setHandleDismissingKeyboard(
        handleDismissingKeyboard handleDismissingKeyboard) {
           this.handleDismissingKeyboard = handleDismissingKeyboard;
    }

    private handleDismissingKeyboard handleDismissingKeyboard;

    public interface handleDismissingKeyboard {
        public void dismissKeyboard();
    }

    @SuppressLint("NewApi")
    public CustomEditText(Context context, AttributeSet attrs,
                             int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        // TODO Auto-generated constructor stub
    }

    public CustomEditText(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    public CustomEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub
    }


    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                && event.getAction() == KeyEvent.ACTION_UP) {
            handleDismissingKeyboard.dismissKeyboard();
            return true;
        }
        return super.dispatchKeyEvent(event);
    }

then in your activity create initialize your CustomEditText and use:

customEditText.setHandleDismissingKeyboard(this);

then implement class and override method and put your code in that

for more info about my answer all thing you need is onKeyPreIme, you can override that in your EditText class ( as i post for you ) to handle all key on that, like back Key or any other keyboard key, I put one inner interface in custom class to get call back from this class to each activity or class that you want, you can do that with static method too, and as you want prevent from dismissing keyboard you can just return true in that.

for using CustomEditText you can use xml or in java, define that and initialize that like other widget ( Button , TextView , ... ), and only different is you need define this in your xml like :

 <yourPackage.CustomEditText ..... />