零零乙 2009-07-10 11:27 采纳率: 33.3%
浏览 840
已采纳

关闭 / 隐藏 Android 软键盘

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 this is a simple piece of code, but where can I find an example of it?

转载于:https://stackoverflow.com/questions/1109022/close-hide-the-android-soft-keyboard

  • 写回答

30条回答 默认 最新

  • ℡Wang Yan 2013-10-24 11:01
    关注

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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(29条)

报告相同问题?

悬赏问题

  • ¥15 Python输入字符串转化为列表排序具体见图,严格按照输入
  • ¥20 XP系统在重新启动后进不去桌面,一直黑屏。
  • ¥15 opencv图像处理,需要四个处理结果图
  • ¥15 无线移动边缘计算系统中的系统模型
  • ¥15 深度学习中的画图问题
  • ¥15 java报错:使用mybatis plus查询一个只返回一条数据的sql,却报错返回了1000多条
  • ¥15 Python报错怎么解决
  • ¥15 simulink如何调用DLL文件
  • ¥15 关于用pyqt6的项目开发该怎么把前段后端和业务层分离
  • ¥30 线性代数的问题,我真的忘了线代的知识了