可靠地隐藏软键盘

15
我有一个应用程序,需要在许多操作中关闭软键盘。例如,单击按钮、绘制新布局、屏幕方向更改、控制器要求 UI 等等。
我使用 optionsMenuButton 来使用 ViewFlipper 翻转视图,显然我希望键盘在翻转的视图中隐藏(那里没有输入字段)。
到目前为止,我尝试了以下方法并说明它们不可靠:
这个方法不起作用,因为我有很多 editText 和其他视图。如果可能的话,我需要一个更通用的方法,不需要视图作为参数。
InputMethodManager imm = (InputMethodManager)getSystemService(
  Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);

对我来说,这个根本不起作用:

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

这个可以工作,但当视图翻转时,立即弹出键盘。

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

这个函数有时可以工作,但大多数时候getCurrentFocus()返回null。

InputMethodManager inputManager = (InputMethodManager)            
Context.getSystemService(Context.INPUT_METHOD_SERVICE); 
inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(),      
InputMethodManager.HIDE_NOT_ALWAYS);

只有在键盘显示时,这个方法才有效:

getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);

这段代码不是针对EditText的,而是针对根布局(root Layout)进行操作。根布局会随着设备旋转和每次onCreate调用而发生变化。我分别为横屏/竖屏以及普通/大屏幕设计了不同的XML布局。所有的根布局都拥有IDroot。第一次使用时效果很好,但之后就无法正常工作了。

InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(findViewById(R.id.root).getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);

总之,我尝试了很多软键盘隐藏方法,但似乎没有一种方法可靠。 是否有任何可靠地隐藏软键盘的方法?

6个回答

9

如果处理getCurrentFocus()的空值情况,就可以解决问题。我使用下面的方法,它非常有效!

     /* Hide Keyboard */
    public static void hideKeyboard(Activity activity){
        InputMethodManager inputMethodManager = (InputMethodManager)activity
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        View focus = activity.getCurrentFocus();
        if(focus != null)
            inputMethodManager.hideSoftInputFromWindow(focus.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }

1
当使用ViewFlipper时,View的焦点为空,因此键盘不会隐藏。可能是与ViewFlipper相关的问题吗? 编辑:也许不是,旋转屏幕也无法隐藏键盘。 - stealthjong
你确定你正在传递正确的活动并在正确的位置调用方法吗?如果键盘打开,我认为视图焦点不应该为空。 - Arda Yigithan Orhan

8

因为需要使用EditText才能调出键盘,所以找到相应的控件后,可以采用你展示的第一种方法来隐藏键盘:

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);

然而,您需要那个EditText。首先获取所有视图:

public static ArrayList<View> getAllViewsFromRoots(View...roots) {
    ArrayList<View> result = new ArrayList<View>();
    for (View root : roots) {
        getAllViews(result, root);
    }
    return result;
}

private static void getAllViews(ArrayList<View> allviews, View parent) {
    allviews.add(parent);
    if (parent instanceof ViewGroup) {
        ViewGroup viewGroup = (ViewGroup)parent;
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            getAllViews(allviews, viewGroup.getChildAt(i));
        }
    }
}

然后,获取一个可见的 EditText

public static EditText getEditText(View root) {
    ArrayList<View> views = getAllViewsFromRoots(root);
    for (View view : views) {
        if (view instanceof EditText && view.getVisibility() == View.VISIBLE) {
            return (EditText) view;
        }
    }
    return null;
}

拨打电话:

Toolkit.getEditText(((ViewParent) findViewById(android.R.id.content)).getChildAt(0));

用此方法,调用隐藏的函数。

经过一些测试,这似乎是最可靠的方法。 - stealthjong
你能发一个代码示例吗?我应该把Toolkit.getEditText(((ViewParent)findViewById(android.R.id.content)).getChildAt(0));放在哪里? - eyal
求婚啦!我已经寻找了很久一个好的解决方案,看起来我找到了一个不错(而且简短)的方法。谢谢! - Tobias Reich

4
这个对我一直有效:
InputMethodManager im = (InputMethodManager) getSystemService(MyActivity.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);

1
把这段代码放在通用的 BaseActivity 中,即可随时在你的 Activity 中调用 hideKeyboard() 方法。同样适用于 Fragment。
open class BaseActivity : AppCompatActivity() {

fun Fragment.hideKeyboard() {
    view?.let { activity?.hideKeyboard(it) }
}

fun Context.hideKeyboard(view: View) {
    val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}

}

0

只有这个解决方案对我起作用:

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

我在一个带有输入框的对话框中进行了对话,但在平板电脑上隐藏对话框并没有隐藏键盘。


0

试试这个:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接