如何使用Java关闭/隐藏Android软键盘? [英] How do you close/hide the Android soft keyboard using Java?

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

问题描述

我的布局中有一个EditTextButton.

在编辑字段中写入并单击Button后,我想在触摸键盘外部时隐藏虚拟键盘.我以为这是一段简单的代码,但是在哪里可以找到它的示例?

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用户道歉,表示谷歌对软键盘的彻底荒谬对待.对于同一个简单问题,答案之所以如此之多,是因为该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 because this API, like many others in Android, is horribly designed. I can think of no polite way to state it.

我想隐藏键盘.我希望为Android提供以下语句:Keyboard.hide().结束.非常感谢你.但是Android有一个问题.您必须使用InputMethodManager隐藏键盘.好的,好的,这是Android键盘上的API.但!您必须具有Context才能访问IMM.现在我们有一个问题.我可能想从没有使用或不需要任何Context的静态或实用程序类中隐藏键盘.或而且,更糟糕的是,IMM要求您指定要隐藏键盘FROM的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键盘,您将需要提供两种形式的标识:ContextViewWindow.

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

请注意,只有从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();

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

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