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

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


当前回答

试试这个

简单,您可以在活动中调用


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

在您的主活动中调用


 hideKeyboardwithoutPopulate(MainActivity.this);

其他回答

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

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

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

这个悲伤的故事以丑陋的事实结尾:要隐藏Android键盘,你需要提供两种形式的标识:上下文和视图或窗口。

我已经创建了一个静态实用程序方法,只要您从“活动”调用它,它就可以非常可靠地完成任务。

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以获取适当的窗口标记。

但是,假设您想对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会自动将初始焦点分配给“活动”中的第一个EditText或可聚焦控件。很自然,InputMethod(通常是软键盘)将通过显示自己来响应焦点事件。AndroidManifest.xml中的windowSoftInputMode属性设置为stateAlwaysHidden时,指示键盘忽略自动分配的初始焦点。

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

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

因此,stateAlwaysHidden的名称确实非常糟糕。它可能应该被称为ignoreInitialFocus。


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

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

如果(view==null)view=new view(activity),则这些是上述代码的替代方案;这些并没有明确提到你的活动。

在片段类中:

view = getView().getRootView().getWindowToken();

给定片段片段作为参数:

view = fragment.getView().getRootView().getWindowToken();

从内容主体开始:

view = findViewById(android.R.id.content).getRootView().getWindowToken();

更新2:如果从后台打开应用程序,请清除焦点以避免再次显示键盘

将此行添加到方法的末尾:

view.clearFocus();

/** 
 *
 *   Hide I Said!!!
 *
 */
public static boolean hideSoftKeyboard(@NonNull Activity activity) {
    View currentFocus = activity.getCurrentFocus();
    if (currentFocus == null) {
        currentFocus = activity.getWindow().getDecorView();
        if (currentFocus != null) {
            return getSoftInput(activity).hideSoftInputFromWindow(currentFocus.getWindowToken(), 0, null);
        }
    }
    return false;
}

public static boolean hideSoftKeyboard(@NonNull Context context) {
   if(Activity.class.isAssignableFrom(context.getClass())){
       return hideSoftKeyboard((Activity)context);
   }
   return false;
}

public static InputMethodManager getSoftInput(@NonNull Context context) {
    return (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
}

用try-catch包围它,这样键盘就已经关闭,应用程序就不会崩溃:

try{

View view = this.getCurrentFocus();
if (view != null) {  
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}catch (Exception e)
{
  e.printStackTrace();
}

这对我有用:

 @Override
 public boolean dispatchTouchEvent(MotionEvent event) {
View v = getCurrentFocus();
boolean ret = super.dispatchTouchEvent(event);

if (v instanceof EditText) {
    View w = getCurrentFocus();
    int scrcoords[] = new int[2];
    w.getLocationOnScreen(scrcoords);
    float x = event.getRawX() + w.getLeft() - scrcoords[0];
    float y = event.getRawY() + w.getTop() - scrcoords[1];

    Log.d("Activity",
            "Touch event " + event.getRawX() + "," + event.getRawY()
                    + " " + x + "," + y + " rect " + w.getLeft() + ","
                    + w.getTop() + "," + w.getRight() + ","
                    + w.getBottom() + " coords " + scrcoords[0] + ","
                    + scrcoords[1]);
    if (event.getAction() == MotionEvent.ACTION_UP
            && (x < w.getLeft() || x >= w.getRight() || y < w.getTop() || y > w
                    .getBottom())) {

        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getWindow().getCurrentFocus()
                .getWindowToken(), 0);
    }
}
return ret;
}

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