题 关闭/隐藏Android软键盘


我有一个 EditText 和a Button 在我的布局中。

在编辑字段中写入并单击后 Button,我想隐藏虚拟键盘。我假设这是一段简单的代码,但我在哪里可以找到它的一个例子?


3093


起源


如果您只有一个EditText和几个按钮,如复选框和无线电,该怎么办?您需要键盘的唯一位置是单个EditText。如何注册以了解为了隐藏键盘而选择/点击了其他内容? - AlikElzin-kilaka
我觉得我好笨。我无法在ICS上隐藏键盘。尝试了这里的所有方法及其组合。没门。显示它的方法有效,但无论什么风口令牌,隐藏旗帜,舱单设置或任何圣徒的蜡烛,我都无法隐藏它。在键盘上我总是看到:I / LatinIME(396):指定了InputType.TYPE_NULL W / LatinIME(396):意外的输入类:inputType = 0x00000000 imeOptions = 0x00000000 - rupps
/ ** *此方法用于隐藏软键盘。 * @param activity * / public void hideSoftKeyboard(Activity activity){InputMethodManager inputMethodManager =(InputMethodManager)activity.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus()。getWindowToken(),0); } - Harshal Benake
很遗憾这个看似简单的问题如此受欢迎。 - lang2
是的,就像Android有简单的一线和两线解决方案。 - milosmns


答案:


为了帮助澄清这种疯狂,我想首先代表所有Android用户道歉,谷歌对软键盘的彻头彻尾的荒谬处理。对于同样简单的问题,有很多答案,每个不同的原因是因为这个API与Android中的许多其他答案一样,设计非常糟糕。我可以想到没有礼貌的方式陈述它。

我想隐藏键盘。我期望为Android提供以下声明: Keyboard.hide()。结束。非常感谢你。但Android存在问题。你必须使用 InputMethodManager 隐藏键盘。好的,很好,这是Android的键盘API。但!你需要有一个 Context 为了访问IMM。现在我们遇到了问题。我可能想要将键盘隐藏在没有任何用途或需要的静态或实用程序类中 Context。或者更糟糕的是,IMM要求您指定什么 View (甚至更糟,是什么 Window)你想隐藏键盘FROM。

这使得隐藏键盘变得如此具有挑战性。亲爱的谷歌:当我查找蛋糕的食谱时,没有 RecipeProvider 在地球上拒绝向我提供食谱,除非我第一次回答世界卫生组织,蛋糕将被吃掉,它会被吃掉!

这个悲伤的故事以丑陋的事实结束:要隐藏Android键盘,您需要提供两种形式的识别:a Context 或者a View 或者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);
}

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

但是假设你想隐藏键盘 EditText 托管在 DialogFragment?你不能使用上面的方法:

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会自动将初始焦点分配给第一个 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();


1024



我不认为你应该修改softInputMode。这将覆盖AndroidManifest设置。 - Kyle Ivey
非常感谢您的回答。雄辩,足以让初学者对软键盘有一个很好的理解。我想隐藏/显示片段的键盘,这是我找到的最合理的答案。 - Tina
好的和有用的答案。这是StackOverflow上非常罕见的帖子之一,很高兴阅读。 - Rameez Hussain
@AlexanderFarber是的,通常是 EditText,但我相信任何可见的 View 会工作(例如 TextView),自从 View 仅用于派生窗口令牌(隐藏键盘的东西)。另外,我相信 View 应该来自主持人 Activity 而不是 Fragment - rmirabelle
@rmirabelle在一个 Fragment 看来你可以用 getActivity().getWindow().getDecorView() - McX


您可以强制Android使用隐藏虚拟键盘 InputMethodManager,打电话 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


4176



如果使用0作为第二个参数,感谢这似乎很有效。但是,如果我使用InputMethodManager.HIDE_IMPLICIT_ONLY,键盘永远不会被隐藏(虽然我没有按住菜单)。任何提示? - RoflcoptrException
凉。只是为了澄清,这只会在存在的情况下驳回它,但不会 避免 它突然冒出来吧? - Cheezmeister
在隐藏softInput之前调用editText.clearFocus()可能会有所帮助 - user2224350
调用 editText.clearFocus() 然后 InputMethodManager.HIDE_IMPLICIT_ONLY 甚至可以工作 4.1 - sprocket12
4.4 / htc对我有用的是执行 View focused = getCurrentFocus() 得到的是什么 无疑 目前专注的观点,呼唤 focused.clearFocus(), 接着 inputMethodManager.hideSoftInputFromWindow(focused.getWindowToken(), 0) (带有清晰的旗帜)。 - Ionoclast Brigham


隐藏软键盘也很有用:

getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
);

这可用于在用户实际触摸editText视图之前抑制软键盘。


742



您还可以通过在清单中的活动中添加android:windowSoftInputMode =“stateHidden”来实现相同的效果。 - BoD
在API级别9上的片段(引用拥有活动)中尝试了这一点,但遗憾的是它无法正常工作。尝试在onResume和onActivityCreated中调用它 - 没有效果。 - AgentKnopf
我正在进行对话,这很有效。我正在使用Android 3.2。我把它放在onCreateDialog(Bundle)方法中。它在onCreate方法中不起作用。对话框对话框= super.onCreateDialog(savedInstanceState); dialog.getWindow()。setSoftInputMode(WindowManager.LayoutParams.SOUTH_INPUT_STATE_ALWAYS_HIDDEN);结果是我的EditTexts视图显示没有键盘。当用户触摸编辑文本时,键盘会显示。 - flobacca
当焦点仍在EditText中时(例如,在触摸按钮后),这不起作用。使用Reto的解决方案。 - Noumenon
为什么重写清单设置是个坏主意?我是从片段中调用它的。没有适用于片段的清单设置...... - Greg Ennis


我还有一个隐藏键盘的解决方案:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

在这里通过 HIDE_IMPLICIT_ONLY 在...的位置 showFlag 和 0 在...的位置 hiddenFlag。它会强行关闭软键盘。


294



你在showflags参数中使用了hide标志。这只能起作用,因为常量使用相同的整数。 使用正确标志的示例 - Alex
在Android 4.0上测试,我喜欢这个解决方案,因为我有多个编辑文本,该活动上的按钮,可以有焦点
为什么这会显示键盘,如果它被隐藏? :)
@Mark:因为该方法被称为“toggleSoftInput”,而不是“hideSoftInput”:) - Sver
此解决方案显示键盘,如果它被隐藏。这是不正确的 - Michael Katkov


Meier的解决方案也适用于我。在我的情况下,我的应用程序的顶级是tabHost,我想在切换标签时隐藏关键字 - 我从tabHost视图中获取窗口标记。

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(tabHost.getApplicationWindowToken(), 0);
    }
}

128



我也使用了SearchView。请参阅下面的答案。谢谢mckoss! - Azurespot


请尝试以下代码 onCreate()

EditText edtView=(EditText)findViewById(R.id.editTextConvertValue);
edtView.setInputType(0);

115



这个方法可以解决2.0和2.1中“无法隐藏软键盘”错误的方法 code.google.com/p/android/issues/detail?id=7115 ...上面列出的hideSoftInputFromWindow方法在我尝试时没有用,但editView.setInputType(0)做了。 - Spike Williams
这是合法的Javadoc(不是黑客),虽然我会重写该方法 editView.setInputType(InputType.TYPE_NULL); - Bostone
但是,它可以隐藏android:提示。我正在使用Android 1.5 - Tirtha
@Bostone这不适用于SearchView - nmxprime
当你需要从对话框中关闭键盘时,这非常适合,不需要获取实例或任何内容,并且可以在用户按下关闭对话框的按钮时将其分配给所有编辑文本 - I'm_With_Stupid


更新: 我不知道为什么这个解决方案不再起作用(我刚刚在Android 23上测试过)。请使用解决方案 Saurabh Pareek 代替。这里是:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
//Hide:
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
//Show
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

老答案:

//Show soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//hide keyboard :
 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

108



我应该在哪里放置此代码?我试图粘贴getWindow()。setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);在onCreate()但键盘永远不会被隐藏 - user2236096
不起作用,在radioGroup.setOnCheckedChangeListener,API 23中测试 - Christian Schäfer
如果仔细观察,InputMethodManager.HIDE_IMPLICIT_ONLY和InputMethodManager.SHOW_IMPLICIT具有相同的值,即“1”,因此这些调用之间没有区别。 =>不工作 - Palejandro
如果调用imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY,0);然后键盘将显示在屏幕上:)最佳实现是: github.com/ravindu1024/android-keyboardlistener Android SDK上的耻辱 - Duna
I don't know why this solution is not work any more - 因为它是 Android的,一切都将能够改变,也许部分是糟糕的设计...我们不小心写,然后我们全力以赴,重写一切。 - King King


protected void hideSoftKeyboard(EditText input) {
    input.setInputType(0);
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}

63



这对我有用!但是你为什么这样说 input.setInputType(0) ?我无法与之互动 EditTextView 当我有那行代码时(当我删除它时它工作)。 - ymerdrengene
@ymerdrengene你是对的,我也必须删除它。 - Lazy


如果这里的所有其他答案对您不起作用,那么还有另一种手动控制键盘的方法。

用它创建一个函数来管理一些 EditText的属性:

public void setEditTextFocus(boolean isFocused) {
    searchEditText.setCursorVisible(isFocused);
    searchEditText.setFocusable(isFocused);
    searchEditText.setFocusableInTouchMode(isFocused);

    if (isFocused) {
        searchEditText.requestFocus();
    }
}

然后,确保onFocus的 EditText 你打开/关闭键盘:

searchEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (v == searchEditText) {
            if (hasFocus) {
                // Open keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(searchEditText, InputMethodManager.SHOW_FORCED);
            } else {
                // Close keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(searchEditText.getWindowToken(), 0);
            }
        }
    }
});

现在,每当你想手动打开键盘时调用:

setEditTextFocus(true);

关闭电话:

setEditTextFocus(false);

58



+1 - 如果要使用闭合键盘启动活动,请使用此解决方案并添加设置setEditTextFocus(true)的onclicklistener。像魅力一样! - schlingel
在第二个代码块的第7行和第10行,我得到了“无法解析符号上下文”。 - gimmegimme
请改用getContext() - Rotemmiz


Saurabh Pareek 到目前为止有最好的答案。

不过,不妨使用正确的旗帜。

/* hide keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

/* show keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

实际使用的例子

/* click button */
public void onClick(View view) {      
  /* hide keyboard */
  ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
      .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

  /* start loader to check parameters ... */
}

/* loader finished */
public void onLoadFinished(Loader<Object> loader, Object data) {
    /* parameters not valid ... */

    /* show keyboard */
    ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
        .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

    /* parameters valid ... */
}

51



在2.1中,键盘弹出,然后隐藏。不好。 - halxinate
这是最新版本的最有效。人们总是需要为旧版本调整它。特别是在v3之前。 - Alex
无法使用Fragments解析方法getSystemService()! - Mazen Kasser
@Mazen:用 fragment.getActivity().getSystemService(); - Johan S
在我的三星标签,Android 5.0,上面所谓的“隐藏键盘”代码将切换软键盘 - 如果它已经隐藏,它将显示它。这个函数在名称中有TOGGLE是有原因的。 - ToolmakerSteve


从搜索到这里,我找到了一个适合我的答案

// Show soft-keyboard:
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

// Hide soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

45