关闭/隐藏Android软键盘


Answers

为了澄清这种疯狂,我想首先代表所有Android用户道歉,因为谷歌对软键盘的彻底荒谬处理。 对于同样简单的问题,有很多答案各不相同,这是因为与Android中的其他许多API一样,这个API的设计非常糟糕。 我可以想到没有礼貌的方式来陈述它。

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

这就是隐藏键盘如此具有挑战性的原因。 亲爱的Google:当我查找蛋糕食谱时,地球上没有RecipeProvider会拒绝为我提供配方,除非我第一次回答WHO蛋糕将被吃掉,并且它将被吃掉!

这个令人伤心的故事以丑陋的真相结束:为了隐藏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调用时才有效! 上述方法调用目标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(通常是软键盘)将通过显示自己来响应焦点事件。 AndroidManifest.xmlwindowSoftInputMode属性设置为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();

Question

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

在编辑栏中写入并单击Button ,我想要隐藏虚拟键盘。 我认为这是一段简单的代码,但我可以在哪里找到它的一个例子?




我有这种情况,我的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 );
}



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



If you want to close the soft keyboard during a unit or functional test, you can do so by clicking the "back button" from your test:

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

I put "back button" in quotes, since the above doesn't trigger the onBackPressed() for the Activity in question. It just closes the keyboard.

Make sure to pause for a little while before moving on, since it takes a little while to close the back button, so subsequent clicks to Views, etc., won't be registered until after a short pause (1 second is long enough ime).




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



我正在使用自定义键盘输入十六进制数字,因此我无法显示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
    }
}

对于旧版本,我用一个OnGlobalLayoutListener获得了非常好的结果(但还远没有完美),并在我的根视图中添加了ViewTreeObserver ,然后检查键盘是否显示如下:

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



For my case, I was using the a SearchView in the actionbar. After a user performs a search, the keyboard would pop open again.

Using the InputMethodManager did not close the keyboard. I had to clearFocus and set the focusable of the search view to false:

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



除此之外,如果您想从任何地方关闭软键盘而无需参考用于打开键盘的(EditText)字段,但仍想在字段集中时进行操作,则可以使用这个(来自一个Activity):

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



简短的答案

在您的OnClick侦听器中使用onEditorAction调用EditTextIME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

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

下钻

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

检查这个相关的答案




请在oncreate()中尝试以下代码

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




Simple and Easy to use method, just call hideKeyboardFrom(YourActivity.this); to hide keyboard

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



This worked for me for all the bizarre keyboard behavior

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



Just use this optimized code in your activity:

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



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

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

这里在HIDE_IMPLICIT_ONLY的位置传递HIDE_IMPLICIT_ONLY ,在HIDE_IMPLICIT_ONLY的位置showFlag 0 。 它会强制关闭软键盘。




Thanks to this SO answer , I derived the following which, in my case, works nicely when scrolling through the the fragments of a 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);
    }
}



Links