关闭 / 隐藏 android 软键盘

我的布局中有一个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?.hideSoftInputFromWindow(v.windowToken, 0)
 }

为了澄清这种疯狂,我首先代表所有 Android 用户道歉,表示谷歌对软键盘的彻底荒谬对待。对于同一个简单问题,答案如此之多,原因各不相同,因为该 API 与 Android 中的许多其他 API 一样,都是经过可怕设计的。我认为没有礼貌的说法。

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

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

这个可悲的故事以一个丑陋的事实结尾:要隐藏 Android 键盘,您将需要提供两种形式的标识: ContextViewWindow

我创建了一个静态实用程序方法,只要您从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或可焦点控件。当然,InputMethod(通常是软键盘)将通过显示自身来响应焦点事件。设置为stateAlwaysHidden时, AndroidManifest.xmlwindowSoftInputMode属性指示键盘忽略此自动分配的初始焦点。

<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 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 imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

这里通过HIDE_IMPLICIT_ONLY在的位置showFlag0在的位置hiddenFlag 。它将强制关闭软键盘。

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

请在onCreate()尝试以下代码

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

更新:我不知道为什么该解决方案不再起作用(我刚刚在 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);
protected void hideSoftKeyboard(EditText input) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}

如果此处所有其他答案都无法满足您的要求,则可以使用另一种手动控制键盘的方法。

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

到目前为止, 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 ... */
}