关闭/隐藏android软键盘


3817

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

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

在键盘外触摸时。


13
如果您只有一个EditText和几个按钮(如复选框和单选框)怎么办?您唯一需要键盘的位置是在单个EditText中。您如何注册才能知道已选择/单击其他东西来隐藏键盘?
2011年

14
我觉得我好笨。我无法隐藏ICS上的键盘。在这里尝试了所有方法及其组合。没门。展示它的方法有效,但无论使用哪种标记,隐藏标志,清单设置或向任何圣徒致以蜡烛,我都无法将其隐藏。在键盘显示上,我总是看到以下内容:I / LatinIME(396):指定了InputType.TYPE_NULL W / LatinIME(396):意外的输入类:inputType = 0x00000000 imeOptions = 0x00000000
rupps

4
/ ** *此方法用于隐藏软键盘。* @param活动* /公共无效hideSoftKeyboard(活动活动){InputMethodManager inputMethodManager =(InputMethodManager)activity.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus()。getWindowToken(),0); }
Harshal Benake 2014年

对我
有用

随着设备屏幕尺寸和分辨率的提高,隐藏虚拟键盘变得越来越不重要。
Al-Kathiri Khalid

Answers:


2031

为了澄清这种疯狂,我首先要代表所有Android用户道歉,感谢Google对软键盘的彻底荒谬对待。对于同一个简单问题,答案之所以如此之多,是因为该API与Android中的许多其他API一样,都是经过可怕设计的。我认为没有礼貌的陈述方式。

我想隐藏键盘。我希望向Android提供以下声明:Keyboard.hide()。结束。非常感谢你。但是Android有一个问题。您必须使用InputMethodManager来隐藏键盘。好的,好的,这是Android键盘的API。但!您需要具有Context才能访问IMM。现在我们有一个问题。我可能想从没有使用或不需要的静态或实用程序类中隐藏键盘Context。或而且,更糟糕的是,IMM要求您指定要隐藏键盘FROM的内容View(或更糟糕的是,内容Window)。

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

这个可悲的故事以一个丑陋的事实结尾:要隐藏Android键盘,您将需要提供2种形式的标识: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);
}

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

但是,假设您要隐藏EditText主机中的键盘DialogFragment?您不能为此使用以上方法:

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

这将不起作用,因为您将传递对Fragment的host 的引用,该宿主ActivityFragment显示时将没有焦点控制!哇!因此,为了隐藏键盘的片段,我求助于较低级别的,更常见的且更难看的:

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


2
非常好写。但是,有一件事,如果您在其上启动另一个活动,这会触发键盘,则返回时键盘仍会存在。通过退出顶级活动时使用您的方法卸下键盘来解决此问题。
Oyvind

3
@rmirabelle在Fragment看来您可以使用getActivity().getWindow().getDecorView()
McX 2015年

1
这篇文章很棒,但是您缺少两个非常重要的部分。每个版本和每个制造商所做的细微更改。例如,在三星银河s6上,我们需要先使用.clearFocus()才能隐藏键盘...否则,键盘在第二次单击edittext时仍会弹出:S
Warpzit

17
Google应该只真正提供该Keyboard.hide();实用程序
HendraWD

1
[someView] .getContext()<<视情况而定。总是同一对象。(内部服务除外...)
奥利弗·迪克森

4416

您可以使用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?.hideSoftInputFromWindow(v.windowToken, 0)
 }

14
谢谢,如果使用0作为第二个参数,这似乎很好用。但是,如果我使用InputMethodManager.HIDE_IMPLICIT_ONLY,则键盘永远不会隐藏(尽管我没有按住菜单)。有什么提示吗?
RoflcoptrException 2010年

27
凉。只是要澄清一下,它只会在存在时将其消除,但不会阻止它弹出,对吗?
Cheezmeister

15
在隐藏softInput之前调用editText.clearFocus()可能会有所帮助
2013年

111
调用editText.clearFocus()那么InputMethodManager.HIDE_IMPLICIT_ONLY即使在工作4.1
sprocket12

11
在4.4 / htc上对我有用的是执行操作,View focused = getCurrentFocus()以获取肯定是当前焦点的视图,调用focused.clearFocus(),然后调用inputMethodManager.hideSoftInputFromWindow(focused.getWindowToken(), 0)(带有清除标志)。
Ionoclast Brigham

805

对于隐藏软键盘也有用的是:

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

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


116
您还可以通过在清单中的活动上添加android:windowSoftInputMode =“ stateHidden”来达到相同的效果。
BoD

7
在API级别9的一个片段(引用了拥有活动)中对此进行了尝试,但不幸的是它没有起作用。尝试在onResume和onActivityCreated中调用它-无效。
AgentKnopf

2
我正在对话中,此方法有效。我正在使用Android 3.2。我把它放在onCreateDialog(Bundle)方法中。它在onCreate方法中不起作用。对话框对话框= super.onCreateDialog(savedInstanceState); dialog.getWindow()。setSoftInputMode(WindowManager.LayoutParams。SOFT_INPUT_STATE_ALWAYS_HIDDEN); 结果是显示的带有EditTexts的视图没有键盘。当用户触摸编辑文本时,将显示键盘。
flobacca

4
当焦点仍在EditText中时(例如,触摸按钮后),此功能将不起作用。为此,请使用Reto的解决方案。
Noumenon

4
为什么覆盖清单设置不是一个好主意?我从一个片段中称呼它。没有适用于片段的清单设置...
Greg Ennis 2014年

348

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

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

路过这里HIDE_IMPLICIT_ONLY时的位置showFlag,并0在该位置hiddenFlag。它将强制关闭软键盘。


4
您在showflags参数中使用了hide标志。这仅起作用,因为常量使用相同的整数。使用正确标志的示例
Alex

在Android 4.0上进行了测试,我喜欢这个解决方案,因为我在该活动上有多个编辑文本,按钮,这些按钮可以具有焦点

32
@马克:因为该方法被称为“toggleSoftInput”,而不是“hideSoftInput” :)
Sver

19
此解决方案显示键盘是否隐藏。这是不正确的
Michael Katkov

1
@AkashAggarwal-如果您忽略它仅因显示键盘而对您有用的事实,则它“起作用”。(它切换了键盘的可见性:在显示时隐藏它,但是在隐藏时显示它!!)您能保证在所有情况下,在所有设备上,对于所有未来的Android版本,键盘都不会在您打电话时显示吗?如果是这样,请继续使用它!
ToolmakerSteve

148

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

我也可以将它与SearchView一起使用。请参阅下面的答案。谢谢mckoss!
Azurespot 2014年

138

请尝试以下代码 onCreate()

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

2
此方法用作避开code.google.com/p/android/issues/detail?id=7115中所述的2.0和2.1中“无法隐藏软键盘”错误的方法... hideSoftInputFromWindow方法我尝试时上面列出的方法不起作用,但是editView.setInputType(0)起作用了。
斯派克·威廉姆斯 Spike Williams)2010年

18
尽管我会将方法重写为editView.setInputType(InputType.TYPE_NULL);
Bostone,

3
这有效,但是,它隐藏了android:hint。我正在使用Android 1.5
Tirtha 2012年

当您需要从对话框中关闭键盘,不需要获取实例或任何东西并且可以在用户按下关闭对话框的按钮时将其分配给所有编辑文本时,这
非常有用

它有效,但也隐藏了光标。我需要光标,但没有系统键盘。
Stefan Brendle '16

128

更新: 我不知道为什么该解决方案不再起作用(我刚刚在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 2013年

不起作用,在radioGroup.setOnCheckedChangeListener中进行了测试,API 23
ChristianSchäfer2015年

如果仔细观察,InputMethodManager.HIDE_IMPLICIT_ONLY和InputMethodManager.SHOW_IMPLICIT的值相同,即为“ 1”,因此这两个调用之间没有区别。=>不工作
Palejandro

如果调用imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY,0); 然后键盘将显示在屏幕上:)最佳实现是:Android SDK上的github.com/ravindu1024/android-keyboardlistener耻辱
Duna

I don't know why this solution is not work any more-因为它是Android,所以一切都会改变,也许部分是由于不良设计而引起的。
King King

88
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);从这段代码中删除了。它改变了键盘行为inputTypeEditText
CoolMind

73

如果此处的所有其他答案对您都不起作用,那么您可以使用另一种手动控制键盘的方法。

创建一个函数,该函数将管理的某些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);

+1-如果要使用关闭的键盘启动活动,请使用此解决方案,并添加一个onclicklistener来设置setEditTextFocus(true)。像魅力一样的作品!
schlingel 2012年

我在第二个代码块的第7行和第10行收到“无法解析符号上下文”。
gimmegimme '17

请改用getContext()
Rotemmiz

61

到目前为止,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之前。
亚历克斯

2
@Mazen:使用fragment.getActivity().getSystemService();
Johan S

这是最全面的答案,包括显示和隐藏。
2014年

4
在我的Samsung Tab Android 5.0上,上面的所谓“隐藏键盘”代码将切换软键盘-如果它已经被隐藏,它将显示它。此功能的名称之所以具有TOGGLE是有原因的。
制造商史蒂夫(Steve)

57

通过这样的搜索,我在这里找到了适合我的答案

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

唯一一款适用于Android 5.1的摩托罗拉的产品
GMX

55

简短的答案

在你的OnClick听众拨打onEditorActionEditTextIME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        someEditText.onEditorAction(EditorInfo.IME_ACTION_DONE)
    }
});

下钻

我觉得这种方法更好,更简单并且更符合Android的设计模式。在上面的简单示例中(通常在大多数常见情况下),您将拥有一个EditText具有/具有焦点的对象,并且通常也是首先要调用键盘的人(肯定可以在许多情况下调用它)常见情况)。用同样的方式释放键盘应该是这样的,通常可以通过来完成ImeAction。刚看到一个EditTextandroid:imeOptions="actionDone"行为,您就想通过相同的方式实现相同的行为。


检查此相关答案


这就是答案。跨版本的唯一方法。我回到这个问题来发布这个答案,因为我不认为其他任何人都知道
Noah Passalacqua 2015年

这应该是正确的答案。我们告诉用户已完成操作,而不是诱使Android隐藏它真正应该放在那里的键盘,这反过来触发了相同的ImeAction [我承认,它是愚蠢的名字],就像用户单击键盘上的“完成”一样。 。这样,如果用户确认键盘上的输入或点击UI按钮,则没有任何区别。
奥利弗·豪斯勒

46

这应该工作:

public class KeyBoard {

    public static void show(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY); // show
    }

    public static void hide(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); // hide
    }

    public static void toggle(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        if (imm.isActive()){
            hide(activity); 
        } else {
            show(activity); 
        }
    }
}

KeyBoard.toggle(activity);

即使部分隐藏了键盘,“ isActive()”也会返回false!
xpto

当然可以,应该这样做。也许我不理解你。无论如何,您可以使用hide()show()方法补充类,以更好地控制何时应显示和何时不显示。为我工作,我也做到了:)我将编辑示例
slinden77

@YoushaAleayoub是的。 KeyBoard.toggle(fragment.getActivity())
slinden77 '16

@ slinden77,大声笑,我是在谈论您的答案...不是您评论的那个。这样答案仍然可以工作。
Yousha Aleayoub

@YoushaAleayoub嗯,会的。最初的问题没有提及片段,您就是提及片段的人。所以我的回答是完全正确的。要将其与片段一起使用,请以不同于的方式调用方法Fragment,例如注释。请先学习如何使用方法,然后再回来。您用愚蠢的答复使人感到困惑
slinden77 '16

43

我正在使用自定义键盘输入十六进制数字,因此无法显示IMM键盘...

在v3.2.4_r1中setSoftInputShownOnFocus(boolean show)已添加了控件,以控制天气或在TextView获得焦点时不显示键盘,但该控件仍处于隐藏状态,因此必须使用反射:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
    try {
        Method method = TextView.class.getMethod("setSoftInputShownOnFocus", boolean.class);
        method.invoke(mEditText, false);
    } catch (Exception e) {
        // Fallback to the second method
    }
}

对于较旧的版本,使用a获得了很好的效果(但远非完美)OnGlobalLayoutListener,并在ViewTreeObserver根视图中借助a 进行了添加,然后检查键盘是否显示如下:

@Override
public void onGlobalLayout() {
    Configuration config = getResources().getConfiguration();

    // Dont allow the default keyboard to show up
    if (config.keyboardHidden != Configuration.KEYBOARDHIDDEN_YES) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
    }
}

最后一个解决方案可能会显示键盘瞬间,并且使选择手柄混乱。

在键盘上进入全屏模式时,不会调用onGlobalLayout。为了避免这种情况,请使用TextView#setImeOptions(int)或在TextView XML声明中:

android:imeOptions="actionNone|actionUnspecified|flagNoFullscreen|flagNoExtractUi"

更新:刚刚找到了用于从不显示键盘的对话框,并且可以在所有版本中使用:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

谢谢。实际上,两个标志FLAG_ALT_FOCUSABLE_IM和FLAG_ALT_FOCUSABLE_IM实际上是对我而言唯一有用的东西。我不希望在活动中显示键盘-即使用户单击编辑文本也不希望显示。(我做了自己的“键盘”)。
丹尼尔·诺瓦克

但是,很酷的解决方案是,如果您的正面活动不是全屏显示,则后面的键盘可见。同样,键盘的光标移动辅助也仍然可见。而且它是不可换肤的。
halxinate

我同意那个。在所有可能的方式中,至少在现有的Android 5.1上,只有getWindow()。setFlags()方法有效。请注意,setSoftInputShownOnFocus()现在为setShowSoftInputOnFocus(),并且不再隐藏但不起作用,至少在用户触摸该字段时不起作用。
olefevre

您的“更新”是我唯一可行的解​​决方案。我正在寻找至少两个小时的解决方案:)
Stefan Brendle

33
public void setKeyboardVisibility(boolean show) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if(show){
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    }else{
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
    }
}

30

我花了两天多的时间来研究线程中发布的所有解决方案,发现它们缺乏一种或另一种方式。我的确切要求是要有一个可以100%可靠性显示或隐藏屏幕键盘的按钮。无论用户单击什么输入字段,都不应再次显示键盘处于隐藏状态时的状态。当它处于可见状态时,无论用户单击什么按钮,键盘都不应消失。这需要一直在Android 2.2及更高版本上运行,直到最新的设备。

您可以在我的应用程序干净RPN中看到此功能的有效实现。

在许多不同的手机(包括froyo和姜饼设备)上测试了许多建议的答案后,很明显,Android应用程序可以可靠地:

  1. 暂时隐藏键盘。当用户聚焦新的文本字段时,它将再次出现。
  2. 活动开始时显示键盘,并在活动上设置一个标志,指示它们的键盘应始终可见。仅当活动正在初始化时才可以设置此标志。
  3. 将活动标记为永不显示或不允许使用键盘。仅当活动正在初始化时才可以设置此标志。

对我来说,暂时隐藏键盘是不够的。在某些设备上,它将在新文本字段聚焦后立即重新出现。当我的应用程序在一页上使用多个文本字段时,聚焦新的文本字段将使隐藏的键盘再次弹出。

不幸的是,列表2和3仅在开始活动时才具有可靠性。活动可见后,您将无法永久隐藏或显示键盘。技巧是在用户按下键盘切换按钮时实际上重新启动您的活动。在我的应用程序中,当用户按下切换键盘按钮时,将运行以下代码:

private void toggleKeyboard(){

    if(keypadPager.getVisibility() == View.VISIBLE){
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        Bundle state = new Bundle();
        onSaveInstanceState(state);
        state.putBoolean(SHOW_KEYBOARD, true);
        i.putExtras(state);

        startActivity(i);
    }
    else{
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        Bundle state = new Bundle();
        onSaveInstanceState(state);
        state.putBoolean(SHOW_KEYBOARD, false);
        i.putExtras(state);

        startActivity(i);
    }
}

这将导致当前活动的状态保存到Bundle中,然后通过一个布尔值启动活动,该布尔值指示应该显示还是隐藏键盘。

在onCreate方法中,运行以下代码:

if(bundle.getBoolean(SHOW_KEYBOARD)){
    ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(newEquationText,0);
    getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
else{
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
            WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}

如果应该显示软键盘,则告诉InputMethodManager显示键盘,并指示窗口使软输入始终可见。如果应该隐藏软键盘,则将设置WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM。

这种方法可以在我测试过的所有设备上可靠地运行-从运行android 2.2的4年旧HTC手机到运行4.2.2的nexus 7。这种方法的唯一缺点是您需要小心处理后退按钮。由于我的应用程序基本上只有一个屏幕(它有一个计算器),因此我可以覆盖onBackPressed()并返回到设备主屏幕。


1
精心设计的解决方法,但我认为,要重新创建数千个对象只是为了隐藏键盘,这实在太多了。我不知道是谁为Android设计了IMM,但是它闻起来像Windows APi。我认为,好的IME应该有两种方法:隐藏和显示:-)
rupps

完全正确,但我的解决方法确实有一个优势-它始终有效!我没有其他解决方案可以始终切换键盘,无论用户界面中的哪些字段具有焦点,用户为切换键盘和键盘所做的操作以及运行的是哪个版本的android:-\
Luke Sleeman

伙计,我非常想隐藏键盘。尝试了成千上万的东西,noooone起作用了。但是您的解决方法对我来说太多了,我必须重新创建10个片段,初始化服务,删除很多WeakReferences ....您知道吗?GC会像25mb一样扔掉:S ...仍在寻找一种可靠的方法来做:(
rupps

@Dmitry好吧,这不是一个好世界...这是平板电脑的复杂应用程序。我拒绝将其完全从内存中卸载,只是为了隐藏一个愚蠢的键盘……无论如何,我发现结合了此处提出的千种解决方案的方法是可行的:)
rupps

27

或者到这一切它的解决方案,如果你想关闭软键盘从任何地方,而不必是用于打开键盘(EditText上)字段的引用,但仍然希望这样做,如果该领域的重点,你可以使用这(来自一个活动):

if (getCurrentFocus() != null) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

25

由于有了这个SO答案,我得到了以下内容,在我的情况下,当滚动浏览ViewPager的片段时,效果很好。

private void hideKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

private void showKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
    }
}

21

上面的答案适用于不同的情况,但是 如果您想将键盘隐藏在视图中并努力获取正确的上下文,请尝试以下操作:

setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        hideSoftKeyBoardOnTabClicked(v);
    }
}

private void hideSoftKeyBoardOnTabClicked(View v) {
    if (v != null && context != null) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

并从构造函数中获取上下文:)

public View/RelativeLayout/so and so (Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
    init();
}

18

如果要在单元测试或功能测试期间关闭软键盘,可以通过单击测试中的“后退按钮”来关闭软键盘:

// Close the soft keyboard from a Test
getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);

我将“后退按钮”用引号引起来,因为上述操作不会触发所onBackPressed()讨论活动的。它只是关闭键盘。

请确保暂停一会儿再继续,因为关闭后退按钮需要一点时间,因此随后的对“视图”等的单击只有在短暂的暂停后才会注册(1秒钟足够长的动画)。


16

这是您在Android版Mono(AKA MonoDroid)中的操作方法

InputMethodManager imm = GetSystemService (Context.InputMethodService) as InputMethodManager;
if (imm != null)
    imm.HideSoftInputFromWindow (searchbox.WindowToken , 0);

1
什么是searchbox在片段?
PCoder 2012年

16

这对于我所有奇怪的键盘行为都有效

private boolean isKeyboardVisible() {
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    mRootView.getWindowVisibleDisplayFrame(r);

    int heightDiff = mRootView.getRootView().getHeight() - (r.bottom - r.top);
    return heightDiff > 100; // if more than 100 pixels, its probably a keyboard...
}

protected void showKeyboard() {
    if (isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if (getCurrentFocus() == null) {
        inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    } else {
        View view = getCurrentFocus();
        inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_FORCED);
    }
}

protected void hideKeyboard() {
    if (!isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    View view = getCurrentFocus();
    if (view == null) {
        if (inputMethodManager.isAcceptingText())
            inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
    } else {
        if (view instanceof EditText)
            ((EditText) view).setText(((EditText) view).getText().toString()); // reset edit text bug on some keyboards bug
        inputMethodManager.hideSoftInputFromInputMethod(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

1
认为我在此之前尝试了10个答案。放弃了希望。谢啦。
Bolling

什么是mRootView?
justdan0227

14

android:windowSoftInputMode="stateHidden"在清单文件中添加到您的活动 中。例:

<activity
            android:name=".ui.activity.MainActivity"
            android:label="@string/mainactivity"
            android:windowSoftInputMode="stateHidden"/>

14

简单易用的方法,只需调用hideKeyboardFrom(YourActivity.this); 隐藏键盘

/**
 * This method is used to hide keyboard
 * @param activity
 */
public static void hideKeyboardFrom(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

13

只需在您的活动中使用以下优化代码即可:

if (this.getCurrentFocus() != null) {
    InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
    inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}

工作良好。谢谢
Alif

12
public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

之后在onTouchListener上调用:

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});

也尝试一下-对我有用:InputMethodManager imm =((InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE)); imm.hideSoftInputFromWindow(getWindow()。getCurrentFocus()。getWindowToken(),0);
zmicer


12

就我而言,我在操作栏中使用了SearchView。用户执行搜索后,键盘将再次弹出打开。

使用InputMethodManager不会关闭键盘。我必须清除focus并将搜索视图的focusable设置为false:

mSearchView.clearFocus();
mSearchView.setFocusable(false);

1
非常聪明。如果用户想要其他搜索,只需再次单击搜索。
亚历克斯

SearchView clearFocus()在Android API页面中没有,因此这对我来说不起作用,但是另一种解决方案起作用了(请参阅下面的答案)。
Azurespot 2014年


12

我的情况是,我的EditText位置也可以位于AlertDialog,所以解雇时应该关闭键盘。以下代码似乎可以在任何地方运行:

public static void hideKeyboard( Activity activity ) {
    InputMethodManager imm = (InputMethodManager)activity.getSystemService( Context.INPUT_METHOD_SERVICE );
    View f = activity.getCurrentFocus();
    if( null != f && null != f.getWindowToken() && EditText.class.isAssignableFrom( f.getClass() ) )
        imm.hideSoftInputFromWindow( f.getWindowToken(), 0 );
    else 
        activity.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN );
}

1
此解决方案更好,因为您不必控制将哪个EditText作为参数传递给hideSoftInputFromWindow()方法。它很棒!!
Billyjoker

12

我几乎尝试了所有这些答案,但我遇到了一些随机问题,尤其是三星s5。

我最终要强迫显示和隐藏,并且效果很好:

/**
 * Force show softKeyboard.
 */
public static void forceShow(@NonNull Context context) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}

/**
 * Force hide softKeyboard.
 */
public static void forceHide(@NonNull Activity activity, @NonNull EditText editText) {
    if (activity.getCurrentFocus() == null || !(activity.getCurrentFocus() instanceof EditText)) {
        editText.requestFocus();
    }
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
    activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.