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

4331
我在我的布局中有一个EditText和一个Button。
在编辑字段中写入内容并点击按钮后,我希望在触摸键盘外部时隐藏虚拟键盘。我认为这是一段简单的代码,但我在哪里可以找到一个例子呢?

19
如果你只有一个 EditText 和多个按钮,比如复选框和单选框,那么唯一需要键盘的地方就是在这个单独的 EditText 中。你该如何注册以便知道其他东西被选择/点击了,以便隐藏键盘? - AlikElzin-kilaka
18
我感觉很蠢。我无法在ICS上隐藏键盘。尝试了这里提供的所有方法,包括它们的各种组合,但都没有用。显示键盘的方法可行,但是无论我使用什么窗口标记、隐藏标志、清单设置或祈求任何圣人,我都无法将其隐藏。每次弹出键盘时我总是看到以下内容: I/LatinIME( 396): InputType.TYPE_NULL is specified W/LatinIME( 396): Unexpected input class: inputType=0x00000000 imeOptions=0x00000000 - rupps
5
/**
  • 此方法用于隐藏软键盘。
  • @param activity 要隐藏软键盘的活动 */ public void hideSoftKeyboard(Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager)activity.getSystemService(Activity.INPUT_METHOD_SERVICE); // 隐藏软键盘 inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0); }
- Harshal Benake
这对我有用。 - nmxprime
你是认真的吗?你不能只是想要隐藏键盘就随时隐藏它吗?无论你有多少按钮、文本或者屏幕有多大,让Android隐藏键盘应该只需要一条指令:S - Windgate
显示剩余2条评论
129个回答

4704
你可以使用InputMethodManager,调用hideSoftInputFromWindow,传入包含你的焦点视图的窗口的令牌,来强制Android隐藏虚拟键盘。
// 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语法
// Only runs if there is a view that is currently focused
this.currentFocus?.let { view ->
    val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
    imm?.hideSoftInputFromWindow(view.windowToken, 0)
}

2
现在getSystemService()需要一个Context和一个serviceClass Class。对于上下文,我可以调用requiredContext,但是对于serviceClass呢? - capo11
1
@capo11 我尝试使用Application.Context.getSystemService(),所以我不需要serviceClass,但它不起作用。 - Windgate
在我的Fragment中使用getActivity().getSystemService()非常有效。 - Captain Jack Sparrow

2559
为了帮助澄清这种混乱,我想代表所有Android用户为Google对软键盘的荒谬处理道歉。为什么对于同一个简单问题有这么多不同的答案呢?原因在于这个API和许多其他Android API一样,设计得非常糟糕。我无法找到一个礼貌的方式来表达它。
我想隐藏键盘。我期望向Android提供以下语句:Keyboard.hide()。结束。非常感谢。但是Android存在一个问题。您必须使用InputMethodManager来隐藏键盘。好吧,这是Android对键盘的API。但是!您需要一个Context才能访问IMM。现在我们有一个问题。我可能想要从一个静态或实用类中隐藏键盘,而这些类没有任何Context的用途或需求。更糟糕的是,IMM要求您指定要从哪个View(甚至更糟糕的是,要从哪个Window)隐藏键盘。
这就是隐藏键盘如此具有挑战性的原因。亲爱的Google:当我查找蛋糕食谱时,地球上没有任何一个RecipeProvider会拒绝向我提供食谱,除非我首先回答蛋糕将由谁食用和在哪里食用!
这个悲伤的故事以丑陋的真相告终:为了隐藏Android键盘,您需要提供两种身份证明:一个Context和一个ViewWindow
我创建了一个静态实用程序方法,可以非常可靠地完成此任务,前提是您从一个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以获取正确的窗口令牌。

但是如果您想要隐藏托管在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);
}

以下是从追寻解决方案的更多时间中获取的一些额外信息:
关于windowSoftInputMode 还有一个需要注意的争议点。默认情况下,Android会自动将初始焦点分配给Activity中的第一个EditText或可聚焦控件。显然,输入法(通常是软键盘)会响应焦点事件并显示自己。当在AndroidManifest.xml中设置windowSoftInputMode属性为stateAlwaysHidden时,会指示键盘忽略此自动分配的初始焦点。请注意保留HTML标签。
<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();


1
为什么需要 getRootView(),而不仅仅是 getView() - ilw
5
一句话翻译:隐藏虚拟键盘。该代码实现了隐藏虚拟键盘的功能,具体实现为:通过获取上下文(Context)对象中的输入法(InputMethodManager)系统服务,调用其hideSoftInputFromWindow方法,传入当前视图(View)的窗口标识符和隐藏选项参数0,以达到隐藏虚拟键盘的效果。 - Martin Braun
1
最近我们终于得到了一个官方的、向后兼容的方法来实现这个(链接见https://dev59.com/vHNA5IYBdhLWcg3wC5Xh#67637849)。 - gmk57
1
最终有了官方的方式 https://dev59.com/vHNA5IYBdhLWcg3wC5Xh#67683124 - Sergey Chilingaryan
请问您能就以下问题提供一下指导吗? :https://stackoverflow.com/questions/67985653/highlight-the-menu-item-found-in-search-result-of-android-settings-app - SVK
显示剩余5条评论

854

隐藏软键盘的另一个有用方法是:

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

这可以用来抑制软键盘,直到用户实际触摸editText视图。


这是2020年唯一有效的方法。我在主活动上有一个编辑文本,并且不希望启动应用程序时弹出键盘。 - Brian M
尝试使用InputMethodManager来处理键盘。可以尝试按照这篇文章操作。 https://androidacademic.blogspot.com/2023/02/closehide-android-soft-keyboard.html - Pragnesh Ghoda シ

389

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

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

showFlag的位置处传递HIDE_IMPLICIT_ONLY,在hiddenFlag的位置处传递0。这将强制关闭软键盘。


6
您在showflags参数中使用了hide标志。这仅适用于常量使用相同的整数。使用正确标志的示例 - Alex
已在Android 4.0上进行了测试。我喜欢这个解决方案,因为在该活动中有多个编辑文本和按钮,可以获得焦点。 - user529543
这对我有效,我没有任何文本框或其他真正具有焦点的东西。 - Basilio German
38
@Mark: 因为该方法被称为“toggleSoftInput”,而不是“hideSoftInput” :) - Sver
2
这个不正常工作。有时会显示键盘。 - Rohaitas Tanoli

170

Meier 的解决方案对我也有用。在我的情况下,我的应用程序的顶层是一个选项卡宿主,并且我想在切换选项卡时隐藏关键字 - 我从选项卡宿主视图获取窗口令牌。

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

我也用SearchView让它工作了。请看下面的答案。感谢mckoss! - Azurespot
嗨,我添加了一个关于Android应用程序开发的新[问题](https://dev59.com/_3gPtIcB2Jgan1znTiEP),您能看一下吗? - Moeez

166

请在onCreate()中尝试下面的代码:

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

3
这种方法可用作解决在Android 2.0和2.1中出现的“无法隐藏软键盘”漏洞,具体内容请参见http://code.google.com/p/android/issues/detail?id=7115...上述提到的hideSoftInputFromWindow方法在我的尝试中不起作用,但是editView.setInputType(0)却有效。 - Spike Williams
22
根据 Javadoc,这是合法的(不是黑客攻击),尽管我会重写该方法为 editView.setInputType(InputType.TYPE_NULL); - Bostone
3
这个方法可行,但会隐藏Android 1.5中的android:hint。 - Tirtha
这很适合在需要从对话框中关闭键盘时使用,不需要获取实例或任何东西,并且可以将其分配给所有编辑文本,当用户按下关闭对话框的按钮时。 - I'm_With_Stupid
它能工作,但同时也隐藏了光标。我需要光标,但不需要系统键盘。 - Stefan Brendle
答案的第二部分是从另一个答案复制的。修订已被回滚。 - General Grievance

157

更新: 我不知道为什么这个解决方案不再起作用了(我刚在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);

8
我应该把这段代码放在哪里?我已经尝试将 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); 粘贴到 onCreate() 中,但键盘从未隐藏。 - user2236096
在radioGroup.setOnCheckedChangeListener中测试过,API 23,但不起作用。 - syr
如果您仔细查看,InputMethodManager.HIDE_IMPLICIT_ONLY和InputMethodManager.SHOW_IMPLICIT具有相同的值,即“1”,因此这些调用之间没有区别。=> 不起作用 - Palejandro
我不知道为什么这个解决方案不再起作用 - 因为它是Android,一切都可能会改变,也许部分原因是设计不良... 我们随意编写,然后划掉所有内容并重新编写。 - King King
工作正常,但实际上在几乎所有三星设备上都会使键盘可见 :) 我喜欢安卓。 - Adam Varhegyi
显示剩余2条评论

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

5
这对我有用!但你为什么要加上 **input.setInputType(0)**?当我有那行代码时,我无法与 EditTextView 进行交互(当我将它移除后它就可以工作了)。 - ymerdrengene
可能是 input.getContext().getSystemService(Context.INPUT_METHOD_SERVICE) - CoolMind
我从这段代码中删除了 input.setInputType(0);。这改变了键盘行为和 EditTextinputType - CoolMind

88

如果其他答案不能满足你的要求,你还有另一种手动控制键盘的方式。

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

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

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

然后,确保在 EditText 的 onFocus 事件中打开/关闭键盘:

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

如果您想要使用关闭键盘的功能启动一个活动,请使用此解决方案,并添加设置setEditTextFocus(true)的onclicklistener。非常好用! - schlingel
我在第二个代码块的第7行和第10行收到了“无法解析符号上下文”的错误。 - gimmegimme
请使用getContext()代替。 - Rotemmiz
上下文 context = View.getContext(); - AgungCode.Com

73

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 ... */
}

1
这是最新版本最有效的方法。对于旧版本,人们总是需要进行调整。特别是在v3之前。 - Alex
2
@Mazen:使用 fragment.getActivity().getSystemService(); - Johan S
这是最全面的答案,涵盖了显示和隐藏两个方面。 - André Staltz
4
不行。在我的三星平板上,Android 5.0系统中,所谓的“隐藏键盘”代码会切换软键盘——如果它已经隐藏了,它会显示出来。这个函数被命名为TOGGLE是有原因的。 - ToolmakerSteve
请您提供以下问题的指导意见: https://stackoverflow.com/questions/67985653/highlight-the-menu-item-found-in-search-result-of-android-settings-app - SVK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接