如何以编程方式关闭/隐藏 Android 软键盘?

Vidar Vestnes

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

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

米拉贝尔

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

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

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

这个悲伤的故事以一个丑陋的事实结束:要隐藏 Android 键盘,您将需要提供 2 种身份识别形式:aContext和 aView或 a 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! getCurrentFocus目标的上述方法调用Activity以获取正确的窗口令牌。

但是假设您想对EditText托管在DialogFragment? 您不能为此使用上述方法:

hideKeyboard(getActivity()); //won't work

这将不起作用,因为您将传递对Fragment's host的引用,在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将自动最初的焦点分配给第一个EditText在你或可聚焦控制Activity很自然地,InputMethod(通常是软键盘)将通过显示自己来响应焦点事件。中的windowSoftInputMode属性AndroidManifest.xml设置为 时stateAlwaysHidden,指示键盘忽略此自动分配的初始焦点。

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

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

因此,stateAlwaysHidden确实是非常糟糕的名字。也许应该ignoreInitialFocus改为调用它


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

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

这些是上述代码的替代方案,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();

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章