我的布局中有一个EditText
和一个Button
。
在编辑字段中写入并单击Button
,我想隐藏虚拟键盘。我假设这是一段简单的代码,但我在哪里可以找到它的一个例子?
您可以使用InputMethodManager强制 Android 隐藏虚拟键盘,调用hideSoftInputFromWindow
,传入包含焦点视图的窗口的标记。
// 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);
}
这将强制键盘在所有情况下都被隐藏。在某些情况下,您需要传入InputMethodManager.HIDE_IMPLICIT_ONLY
作为第二个参数,以确保您只在用户未明确强制显示键盘时隐藏键盘(通过按住菜单)。
注意:如果要在 Kotlin 中执行此操作,请使用: context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
Kotlin 语法
// Check if no view has focus:
val view = this.currentFocus
view?.let { v ->
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.let { it.hideSoftInputFromWindow(v.windowToken, 0) }
}
为了帮助澄清这种疯狂,我想首先代表所有 Android 用户道歉,谷歌对软键盘的彻头彻尾的荒谬处理。对于同样简单的问题,有这么多答案的原因有很多,因为这个 API 与 Android 中的许多其他 API 一样,设计非常糟糕。我认为没有礼貌的方式来陈述它。
我想隐藏键盘。我期望为 Android 提供以下声明: Keyboard.hide()
。结束。非常感谢你。但 Android 存在问题。您必须使用InputMethodManager
来隐藏键盘。好的,很好,这是 Android 的键盘 API。但!您需要具有Context
才能访问 IMM。现在我们遇到了问题。我可能想要从没有任何使用或不需要任何Context
的静态或实用程序类中隐藏键盘。或者更糟糕的是,IMM 要求您指定要隐藏键盘 FROM 的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
显示!哇!所以,为了从键盘中隐藏键盘,我采用较低级别,更常见,更丑陋:
public static void hideKeyboardFrom(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
以下是从追求此解决方案浪费的更多时间中收集的一些其他信息:
关于 windowSoftInputMode
还有另一个争论点需要注意。默认情况下,Android 会自动将初始焦点分配给Activity
的第一个EditText
或 focusable 控件。由此可见,InputMethod(通常是软键盘)将通过显示自身来响应焦点事件。 AndroidManifest.xml
的windowSoftInputMode
属性设置为stateAlwaysHidden
,指示键盘忽略此自动分配的初始焦点。
<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateAlwaysHidden"/>
几乎令人难以置信的是,当您触摸控件时,似乎无法阻止键盘打开(除非将focusable="false"
和 / 或focusableInTouchMode="false"
分配给控件)。显然,windowSoftInputMode 设置仅适用于自动焦点事件,而不适用于触摸由触摸事件触发的事件。
因此, stateAlwaysHidden
名字确实非常糟糕。它也许应该被称为ignoreInitialFocus
。
希望这可以帮助。
更新:获取窗口令牌的更多方法
如果没有焦点视图(例如,如果您刚刚更改了片段,则会发生),还有其他视图将提供有用的窗口令牌。
if (view == null) view = new View(activity);
这些是上述代码的替代品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();
更新 2:如果您从后台打开应用程序,请清除焦点以避免再次显示键盘
将此行添加到方法的末尾:
view.clearFocus();
隐藏软键盘也很有用:
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
);
这可用于在用户实际触摸 editText 视图之前抑制软键盘。
您可以使用InputMethodManager强制 Android 隐藏虚拟键盘,调用hideSoftInputFromWindow
,传入包含焦点视图的窗口的标记。
// 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);
}
这将强制键盘在所有情况下都被隐藏。在某些情况下,您需要传入InputMethodManager.HIDE_IMPLICIT_ONLY
作为第二个参数,以确保您只在用户未明确强制显示键盘时隐藏键盘(通过按住菜单)。
注意:如果要在 Kotlin 中执行此操作,请使用: context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
Kotlin 语法
// Check if no view has focus:
val view = this.currentFocus
view?.let { v ->
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.let { it.hideSoftInputFromWindow(v.windowToken, 0) }
}
为了帮助澄清这种疯狂,我想首先代表所有 Android 用户道歉,谷歌对软键盘的彻头彻尾的荒谬处理。对于同样简单的问题,有这么多答案的原因有很多,因为这个 API 与 Android 中的许多其他 API 一样,设计非常糟糕。我认为没有礼貌的方式来陈述它。
我想隐藏键盘。我期望为 Android 提供以下声明: Keyboard.hide()
。结束。非常感谢你。但 Android 存在问题。您必须使用InputMethodManager
来隐藏键盘。好的,很好,这是 Android 的键盘 API。但!您需要具有Context
才能访问 IMM。现在我们遇到了问题。我可能想要从没有任何使用或不需要任何Context
的静态或实用程序类中隐藏键盘。或者更糟糕的是,IMM 要求您指定要隐藏键盘 FROM 的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
显示!哇!所以,为了从键盘中隐藏键盘,我采用较低级别,更常见,更丑陋:
public static void hideKeyboardFrom(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
以下是从追求此解决方案浪费的更多时间中收集的一些其他信息:
关于 windowSoftInputMode
还有另一个争论点需要注意。默认情况下,Android 会自动将初始焦点分配给Activity
的第一个EditText
或 focusable 控件。由此可见,InputMethod(通常是软键盘)将通过显示自身来响应焦点事件。 AndroidManifest.xml
的windowSoftInputMode
属性设置为stateAlwaysHidden
,指示键盘忽略此自动分配的初始焦点。
<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateAlwaysHidden"/>
几乎令人难以置信的是,当您触摸控件时,似乎无法阻止键盘打开(除非将focusable="false"
和 / 或focusableInTouchMode="false"
分配给控件)。显然,windowSoftInputMode 设置仅适用于自动焦点事件,而不适用于触摸由触摸事件触发的事件。
因此, stateAlwaysHidden
名字确实非常糟糕。它也许应该被称为ignoreInitialFocus
。
希望这可以帮助。
更新:获取窗口令牌的更多方法
如果没有焦点视图(例如,如果您刚刚更改了片段,则会发生),还有其他视图将提供有用的窗口令牌。
if (view == null) view = new View(activity);
这些是上述代码的替代品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();
更新 2:如果您从后台打开应用程序,请清除焦点以避免再次显示键盘
将此行添加到方法的末尾:
view.clearFocus();
隐藏软键盘也很有用:
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
);
这可用于在用户实际触摸 editText 视图之前抑制软键盘。