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

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


当前回答

public void hideKeyboard() 
{
    if(getCurrentFocus()!=null) 
    {
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
    }
}


public void showKeyboard(View mView) {
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
    mView.requestFocus();
    inputMethodManager.showSoftInput(mView, 0);
}

其他回答

通过创建一个扩展来隐藏Kotlin中的软键盘,您可以全局使用该扩展。为此,需要创建一个Singleton类。

object Extensions {
    
      fun View.hideKeyboard() {
            val inputMethodManager =                                                 
            context.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE)           
            as InputMethodManager
            inputMethodManager.hideSoftInputFromWindow(windowToken, 0)
        }
    }

在需要隐藏键盘的片段类的活动中,可以使用mainlayout id调用此函数,如下所示

//constraintEditLayout is my main view layout, if you are using other layout like relative or linear layouts you can call with that layout id
constraintEditLayout.hideKeyboard()

Android 11中有一个名为WindowInsetsController的新API,应用程序可以从任何视图访问控制器,通过它我们可以使用hide()和show()方法

val controller = view.windowInsetsController

// Show the keyboard (IME)
controller.show(Type.ime())

// Hide the keyboard
controller.hide(Type.ime())

看见https://developer.android.com/reference/android/view/WindowInsetsController

为了帮助澄清这种疯狂,我想首先代表所有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();

当您想手动隐藏键盘时,单击按钮:

/**
 * Hides the already popped up keyboard from the screen.
 *
 */
public void hideKeyboard() {
    try {
        // use application level context to avoid unnecessary leaks.
        InputMethodManager inputManager = (InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        assert inputManager != null;
        inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

当您想在屏幕上除编辑文本以外的任何地方隐藏键盘时在活动中重写此方法:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    View view = getCurrentFocus();
    if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) {
        int scrcoords[] = new int[2];
        view.getLocationOnScreen(scrcoords);
        float x = ev.getRawX() + view.getLeft() - scrcoords[0];
        float y = ev.getRawY() + view.getTop() - scrcoords[1];
        if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom())
            ((InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((this.getWindow().getDecorView().getApplicationWindowToken()), 0);
    }
    return super.dispatchTouchEvent(ev);
}

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