如何以编程方式关闭/隐藏 Android 软键盘? [英] How do you close/hide the Android soft keyboard programmatically?

查看:55
本文介绍了如何以编程方式关闭/隐藏 Android 软键盘?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的布局中有一个 EditText 和一个 Button.

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 when touching outside the keyboard. I assume that this is a simple piece of code, but where can I find an example of it?

推荐答案

为了帮助澄清这种疯狂,我首先代表所有 Android 用户对 Google 对软键盘的彻头彻尾的荒谬处理表示歉意.对于同一个简单的问题,有这么多不同的答案的原因是,这个 API 与 Android 中的许多其他 API 一样,设计得非常糟糕.我想不出礼貌的方式来表达它.

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 that this API, like many others in Android, is horribly designed. I can think of no polite way to state it.

我想隐藏键盘.我希望为 Android 提供以下语句:Keyboard.hide().结束.非常感谢.但是安卓有问题.您必须使用 InputMethodManager 来隐藏键盘.好的,好的,这是 Android 的键盘 API.但!您需要有一个 Context 才能访问 IMM.现在我们有一个问题.我可能想对一个没有使用或不需要任何 Context 的静态或实用程序类隐藏键盘.或者更糟糕的是,IMM 要求您指定要隐藏键盘的 View(或更糟的是,什么 Window).

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.

这就是隐藏键盘如此具有挑战性的原因.亲爱的 Google:当我查找蛋糕的食谱时,地球上没有 RecipeProvider 会拒绝向我提供食谱,除非我先回答谁会吃蛋糕以及在哪里吃会被吃掉!!

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!!

这个悲伤的故事以一个丑陋的事实结束:要隐藏 Android 键盘,您将需要提供两种形式的标识:ContextView窗口.

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.

我创建了一个静态实用方法,可以非常稳定地完成这项工作,前提是您从 Activity 调用它.

I have created a static utility method that 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);
}

请注意,此实用程序方法仅在从 Activity 调用时才有效!上述方法调用目标ActivitygetCurrentFocus来获取正确的窗口令牌.

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.

但是假设您想对 DialogFragment 中托管的 EditText 隐藏键盘?您不能为此使用上述方法:

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

这将不起作用,因为您将传递对 Fragment 的宿主 Activity 的引用,而 Fragment 将没有焦点控制 显示!哇!所以,为了隐藏键盘碎片,我求助于较低级别的、更常见的、更丑的:

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:

关于windowSoftInputMode

还有一个需要注意的争论点.默认情况下,Android 会自动将初始焦点分配给 Activity 中的第一个 EditText 或可聚焦控件.很自然地,InputMethod(通常是软键盘)将通过显示自己来响应焦点事件.AndroidManifest.xml 中的 windowSoftInputMode 属性设置为 stateAlwaysHidden 时,会指示键盘忽略此自动分配的初始焦点.

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"/>

几乎令人难以置信的是,当您触摸控件时,它似乎没有阻止键盘打开(除非 focusable=false" 和/或 focusableInTouchMode=false" 分配给控件).显然,windowSoftInputMode 设置只适用于自动焦点事件,不适用于触摸事件触发的焦点事件.

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 by touch events.

因此,stateAlwaysHidden 的命名确实很糟糕.它或许应该被称为 ignoreInitialFocus.

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

更新:获取窗口令牌的更多方法

如果没有焦点视图(例如,如果您只是更改片段可能会发生这种情况),还有其他视图将提供有用的窗口标记.

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.

这些是上述代码的替代方案 if (view == null) view = new View(activity); 这些没有明确指代您的活动.

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

在片段类中:

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

给定一个片段 fragment 作为参数:

Given a fragment fragment as a parameter:

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

从您的内容正文开始:

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


更新 2:清除焦点以避免在从后台打开应用程序时再次显示键盘

将这一行添加到方法的末尾:

Add this line to the end of the method:

view.clearFocus();

这篇关于如何以编程方式关闭/隐藏 Android 软键盘?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆