强制打开软键盘

53

我正在尝试在一个Activity中强制打开软键盘,并获取所有输入的内容,因为我想自己处理输入,但是我没有EditText。目前我已经尝试过这个方法,但它不起作用。我希望软键盘在mAnswerTextView下方打开(注意:它是一个TextView而不是EditText)。

    InputMethodManager mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    // only will trigger it if no physical keyboard is open
    mgr.showSoftInput(mAnswerTextView, InputMethodManager.SHOW_IMPLICIT);
  1. 如何强制打开软键盘
  2. 我该如何获取输入的每个字符,以便可以处理它们?我想在处理完每个字符后将其清空。即用户不应该能够在软键盘中输入整个单词。

嗨, 我和你有同样的问题。我能够显示键盘,但是如果没有EditText,我该如何获取输入的所有内容呢? 谢谢! - Sebastian Breit
11个回答

138

尝试以下方法来强制打开软键盘:

((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);

然后你可以使用以下代码关闭键盘:

((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(_pay_box_helper.getWindowToken(), 0);

1
谢谢。在“关闭键盘”示例中,_pay_box_helper是什么?编辑:啊,我明白了,它是一个文本字段变量。 - Ben Clayton
对我来说非常好用,在可折叠菜单上编辑Action Bar Sherlock的文本。谢谢。 - Soham
1
在Lollipop中,我的碎片EditText的唯一解决方案。 - scorpiodawg

15

你可能需要一个可编辑的文本区域来获得焦点。你可以使用一个不可见或透明背景且没有光标的文本区域。你可能需要调整视图的焦点设置。

使用addTextChangedListener设置TextWatcher以检查对EditText的编辑,或者如果你需要更低级别的钩子,使用setOnKeyListener()方法设置textview的键监听器。请参阅KeyListener documentation

使用此调用强制打开软键盘:

((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE))
    .showSoftInput(myEditText, InputMethodManager.SHOW_FORCED);

还有这个来关闭它:

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

请注意,这真的不推荐使用 - 强制打开键盘有点混乱。你的用例是什么,确实需要在没有普通编辑框的情况下获取用户输入,并需要按键处理用户输入而不将其回显?

我从Droid那里收到了大量的错误信息。特别是java.lang.IndexOutOfBoundsException: getChars (6 ... 0)出现了起始位置在结束位置之后的bug。这是由于EditText引起的。 - jax
由于哪个EditText?这个错误是来自TextWatcher、KeyListener还是showSoftInput/hideSoftInput调用?你还需要发布你的代码和堆栈跟踪,以便任何人能够在这里帮助你。 - Yoni Samlan
2
showSoftInput()在第一次尝试时并不总是有效。我发现我必须在视图上重复两次操作才能显示出来。 - IgorGanapolsky
1
重要提示:InputMethodManager.SHOW_FORCED 不是 showSoftInput() 方法的有效标志!只有 0InputMethodManager.SHOW_IMPLICIT 是有效的标志! - Rolf ツ
请注意执行此命令的时机。有时候,视图尚未呈现。 - Lucas Moretto

8

有时其他的答案可能不适用。
这里提供一种另外的方法。

通过监听窗口焦点,它将强制在活动开始时显示键盘。 onWindowFocusChanged() 将清除并请求 EditText 的焦点,然后将软输入模式设置为可见,并将选择设置为框中的文本。如果您是从活动中调用它,这应该始终有效。

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        mEditText.clearFocus();
        mEditText.requestFocus();
        getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
        mEditText.setSelection(mEditText.getText().toString().length());
    }
}

您可能还需要:
mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.showSoftInput(mEditText, InputMethodManager.SHOW_IMPLICIT);
            }
        }
    });

编辑:我也看到了键盘在嵌套碎片中不打开的情况,请注意这种情况。


嵌套片段是我正在努力实现的。这可能是一个真实的陈述。 - carl

8
为了强制打开键盘,我使用了下面的方法:
this.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);

这对我很有用。


1
对我来说可以运行,但你必须在'onCreate'中的'super.onCreate()'之前调用它。 - Palani
不起作用。在 .onCreate 中在 super 之前调用会创建一个 null。这也是错误的方法。 - carl

2
很遗憾,尽管我很想点赞其中一条回复,但都对我没用。看来解决方案是等待布局阶段完成。在下面的代码中,请注意我如何检查showKeyboard方法是否返回TRUE,然后我就移除全局布局监听器。如果不这样做,有时能成功,有时会失败。现在它似乎完美地工作了。
最好在onResume()中执行以下操作。
@Override
public void onResume()
{
    super.onResume();

    ViewTreeObserver vto = txtTaskTitle.getViewTreeObserver();
            vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
            {
                @Override
                public void onGlobalLayout()
                {
                    if (txtTaskTitle.requestFocus())
                    {
                        if (showKeyboard(getContext(), txtTaskTitle))
                        {
                            txtTaskTitle.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                        }
                    }
                }
            });
}

public static boolean showKeyboard(Context context, EditText target)
{
        if (context == null || target == null)
        {
            return false;
        }

        InputMethodManager imm = getInputMethodManager(context);

        ((InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(target, InputMethodManager.SHOW_FORCED);

        boolean didShowKeyboard = imm.showSoftInput(target, InputMethodManager.SHOW_FORCED);
        if (!didShowKeyboard)
        {
            didShowKeyboard = ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(target, InputMethodManager.SHOW_FORCED);
        }
        return didShowKeyboard;
}

2

如果您想在活动中控制软键盘,请使用以下代码:

//create soft keyboard object
InputMethodManager imm = (InputMethodManager)this.getSystemService(INPUT_METHOD_SERVICE);

//1.USE
your_view.setFocusableInTouchMode(true); //Enable touch soft keyboard to this view
//or
your_view.setFocusable(true); //Enable keyboard to this view
imm.showInputMethod(your_view, InputMethodManager.SHOW_IMPLICIT);

//2.USE show keyboard if is hidden or hide if it is shown
imm.toggleSoftInputFromWindow(your_view.getWindowToken(),InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);
//or
imm.toggleSoftInputFromWindow(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);

//3.USE (you cannot control imm)
this.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);

//4.USE (with Dialog)
Dialog d = new Dialog(this, android.R.style.Theme_Panel);
d.getWindow().setTitle(null);
d.setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
d.setOnKeyListener(keyListener);
d.setCanceledOnTouchOutside(true);
d.setCancelable(true);
d.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
d.show();

//to hide keyboard call:
d.dismiss();
//if you want get soft keyboard visibility call:
d.isShowing();

1

工作得很好……

edt_searchfilter_searchtext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus){
                edt_searchfilter_searchtext.post(new Runnable() {
                    @Override
                    public void run() {
                        InputMethodManager imm = (InputMethodManager) getFragmentActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                        imm.showSoftInput(edt_searchfilter_searchtext, InputMethodManager.SHOW_IMPLICIT);
                    }
                });
            }
        }
    });

以下代码行在需要打开键盘时调用。
 edt_searchfilter_searchtext.requestFocus();

0

简单来说,只需添加两行代码即可完美解决:

如果使用XML

android:focusable="true"
android:focusableInTouchMode="true"

Java中的Else:

view.setFocusableInTouchMode(true);
view.requestFocus();

0
if(search.getText().toString().trim().isEmpty()) {
    InputMethodManager imm = (InputMethodManager)getSystemService(
              Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(search.getWindowToken(), 0);
}

1
请在代码中添加为什么/如何回答问题的解释?仅有代码的回答是不被鼓励的,因为相比具有解释的代码,它们不容易学习。没有解释需要更多的时间和精力来理解所做的工作、对代码进行的更改、代码是否回答了问题等。解释对于试图从答案中学习的人以及评估答案的人来说都很重要,以确定其是否有效或值得投票支持。 - Makyen

0
我已经测试过,这个是有效的:

... //显示软键盘

imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

//要隐藏它,请再次调用该方法

imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

2
糟糕的复制粘贴 - webbi

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