我的布局中有EditText
和Button
.
在编辑字段中写入并单击Button
之后,我想在touch 键盘外部时隐藏虚拟键盘.我假设这是一段简单的代码,但在哪里可以找到它的示例?
我的布局中有EditText
和Button
.
在编辑字段中写入并单击Button
之后,我想在touch 键盘外部时隐藏虚拟键盘.我假设这是一段简单的代码,但在哪里可以找到它的示例?
为了澄清这种疯狂,我想首先代表所有安卓用户为谷歌对软键盘的荒谬处理道歉.对于同一个简单的问题,有如此多的答案,每个答案都不同,原因是这个API和Android中的许多其他API一样,设计得非常糟糕.我想不出有礼貌的说法.
我想把键盘藏起来.我希望为Android提供以下声明:Keyboard.hide()
.结束了.非常感谢你.但安卓有一个问题.你必须使用InputMethodManager
隐藏键盘.好的,这是Android的键盘API.但是您必须拥有Context
才能访问IMM.现在我们有问题了.我可能想对一个静态类或实用类隐藏键盘,这个类没有任何用途或需要.或者更糟糕的是,IMM要求您指定要隐藏键盘的内容View
(甚至更糟,是Window
).
这就是隐藏键盘如此具有挑战性的原因.亲爱的谷歌:当我在查找蛋糕的配方时,地球上没有RecipeProvider
家公司会拒绝向我提供配方,除非我首先回答谁会吃蛋糕以及在哪里吃蛋糕!!
这个悲惨的故事以丑陋的事实结束:要隐藏Android键盘,你需要提供两种身份证明:Context
和View
或Window
.
我已经创建了一个静态实用程序方法,可以非常可靠地完成这项工作,只要你从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
调用时有效!上述方法调用目标Activity
的getCurrentFocus
来获取正确的窗口令牌.
但是,假设您想在DialogFragment
中托管的EditText
中隐藏键盘?您不能使用上述方法:
hideKeyboard(getActivity()); //won't work
这不会起作用,因为您将传递一个对Fragment
的宿主Activity
的引用,在显示Fragment
时,宿主Activity
将没有焦点控件!哇!因此,为了从碎片中隐藏键盘,我求助于更低级别、更常见、更难看的键盘:
public static void hideKeyboardFrom(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
以下是从花费更多时间追求此解决方案中收集到的一些附加信息:
About windowSoftInputMode个
还有另一个争论点需要注意.默认情况下,Android会自动将初始焦点分配给Activity
中的前EditText
个或可聚焦控件.很自然地,InputMethod(通常是软键盘)会通过显示自己来响应聚焦事件.AndroidManifest.xml
中的windowSoftInputMode
属性设置为stateAlwaysHidden
时,指示键盘忽略自动分配的初始焦点.
<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateAlwaysHidden"/>
几乎令人难以置信的是,当你touch 控件时,它似乎没有阻止键盘打开(除非为控件指定了focusable="false"
和/或focusableInTouchMode="false"
).显然,WindowsofInputMode设置仅适用于自动对焦事件,而不适用于由touch 事件触发的对焦事件.
因此,stateAlwaysHidden
确实是一个非常糟糕的名字.它或许应该被称为ignoreInitialFocus
.
UPDATE: More ways to get a window token
如果没有聚焦视图(例如,如果您只是更改了片段,可能会发生这种情况),那么还有其他视图将提供有用的窗口标记.
这些都是上述代码if (view == null) view = new View(activity);
的替代代码,它们并不显式地引用您的活动.
在片段类中:
view = getView().getRootView().getWindowToken();
给定一个片段fragment
作为参数:
view = fragment.getView().getRootView().getWindowToken();
从你的内容主体开始:
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
将这一行添加到方法的末尾:
view.clearFocus();