当使用AlertDialog.Builder与EditText时,软键盘不会弹出。

125
我正在使用AlertDialog.Builder创建一个带有EditText作为输入方法的输入框。不幸的是,虽然EditText处于焦点状态,但软键盘并没有弹出,除非你再次显式地触摸它。是否有一种方式可以强制让它弹出?我在(AlertDialog.Builder).show()之后尝试了以下方法,但无济于事。
InputMethodManager mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
mgr.showSoftInput(input, InputMethodManager.SHOW_FORCED);

有人可以帮忙吗?

谢谢!!


1
请格式化您的源代码。 - philipp
那我也给你点个赞 :) 我之前也遇到了同样的问题,搜寻了好几个小时,最后grine4ka的回答解决了我的问题。 - philipp
14个回答

231

我已经做了这样的事情

AlertDialog.Builder b = new AlertDialog.Builder(this);//....
AlertDialog dialog = b.create();

dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);

dialog.show();

3
非常感谢。我已经搜索了一段时间,这是你想走的方式。所有的 OnFocusChangeListener 方法对我来说似乎都太过麻烦并会引起问题。 你需要从 AlertDialog.Builder 中创建 AlertDialog - philipp
这真的是一个解决方案吗?这只是强制显示键盘,无论是否有输入字段,无论输入字段是否具有焦点,是吗?=) - Ted
1
我实际上设法“解决了”(解决方法)。我使用setOnFocusChangeListener来监听EditText,然后在onFocusChange中检查它是否有焦点(“hasFocus”变量),如果是,则执行getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)。 - Ted
1
注意:为了使其正常工作,您需要在dialog.show()之前放置setSoftInputMode行。顺便说一句,简单正确的解决方案加1。 - Spikatrix
2
如果它无法工作,请添加一行 "edittext.requestFocus()",这对我有效。 - BlueMist
显示剩余6条评论

31

我已经这样解决了:

Dialog = builder.create();
Dialog.show();
Dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE  | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
Dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);

1
请注意,在Android 4-8上,在调用dialog.show()之后再调用dialog.getWindow().setSoftInputMode()会产生一个不好的副作用:对话框在配置更改后仍然停留在屏幕上,仍然与已销毁的Activity/Fragment绑定。 - gmk57

25

我发现同样的代码在平板电脑上能够正常工作,键盘会弹出,但在手机上却不行,因此进一步研究后,似乎指向了“adjust”选项。

我正在使用这个,感觉更加清洁。

AlertDialog d = builder.create();
d.getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
d.show();

谢谢。这比使用SOFT_INPUT_STATE_ALWAYS_VISIBLE要好得多。因为SOFT_INPUT_STATE_ALWAYS_VISIBLE会阻塞对话框的UI组件,而SOFT_INPUT_ADJUST_RESIZE可以调整大小并将对话框“推上去”。 - Cheok Yan Cheng

14

在我的情况下,当显示对话框时唯一可以显示键盘的方法是向我的 DialogFragment 添加以下内容:

@Override
public void onResume() {
    super.onResume();
    getDialog().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    myEditText.requestFocus();
}

请注意使用SOFT_INPUT_STATE_ALWAYS_VISIBLE而不是SOFT_INPUT_STATE_VISIBLE

来自文档:

// Visibility state for softInputMode: please always make the soft input 
// area visible when this window receives input focus.
int SOFT_INPUT_STATE_ALWAYS_VISIBLE;

这是唯一一个对我有效的解决方案,而且我尝试了很多其他方法。我的问题是从AlertDialog Builder构建的DialogFragment。重要的部分似乎是将上述代码放置在onResume()中。在其他任何地方都不起作用! - user960914
这个解决方案非常有效。虽然这个解决方案是针对对话框片段的,但它在AlertDialog上也很好用,我认为它适用于任何类型的对话框。只需在调用AlertDialogshow()方法后加入这三行代码,然后请求输入视图的焦点即可。 - Kozmotronik

7

当您调用showDialog()以显示使用AlertDialogonCreateDialog()中创建的对话框时,您应该将代码放在onPrepareDialog()中:

@Override
protected void onPrepareDialog (int id, Dialog dialog, Bundle args)
{
    TextView editText=(TextView) dialog.findViewById(R....);

    editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
       @Override
       public void onFocusChange(View v, boolean hasFocus) {
         if (hasFocus) {
            dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
         }
       }
    });
}

7

这里提供了一个更好的解决方案,请点击此处

dialog.getWindow().clearFlags(
         WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        |WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

没有解决方法。 EditText 的行为与预期相同。

这个对我有用,其他的解决方案可以将焦点带到输入框,但键盘没有弹出。 - Akshay

5

我的情况是,在创建对话框后设置了SoftInputMode,但它没有显示出来。以下代码适用于我,在显示对话框后设置了SoftInputMode。

Kotlin:

val dialog = MaterialAlertDialogBuilder(context) // Other builder code
                .create()
dialog.show()
dialog.window?.apply { // After the window is created, get the SoftInputMode
    clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
    clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
    setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
}

Java:

AlertDialog dialog = MaterialAlertDialogBuilder(getContext()) // Other builder code
                .create();
dialog.show();
Window window = dialog.getWindow();
if(window != null){ // After the window is created, get the SoftInputMode
    window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
    window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}

我希望这可以帮助和我遇到相同问题的任何人。

2
Window window = dialog.getWindow();
    window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

1

这个问题在这里已经有答案了。对我来说,使用OnFocusChangeListener解决了问题。


问题是如何为AlertDialog.Builder对象设置软输入模式,但是您提到的线程使用了一个AlertDialog对象的示例。如果我尝试使用建议的代码(在OnFocusChangeListener中使用alert.getWindow().setSoftInputMode(...)),Eclipse会抱怨方法getWindow()未定义于AlertDialog.Builder类型。请问您能帮我解决这个问题吗? - prepbgg

1

当AlertDialog.onCreate被调用后添加EditText时,会出现此问题。

https://developer.android.com/reference/androidx/appcompat/app/AlertDialog.Builder

AlertDialog类会根据对话框内的视图是否从View.onCheckIsTextEditor()返回true自动设置android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM标志,您需要清除FLAG_ALT_FOCUSABLE_IM标志。
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 

由于AlertDialog.show是在DialogFragment.onStart中调用的,因此您可以将代码插入到DialogFragment.onStart中。

@Override
public void onStart() {
    super.onStart();
    getDialog().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}

如果您不使用DialogFragment,也可以使用Dialog.setOnShowListener。

dialog.setOnShowListener(new DialogInterface.OnShowListener() {
    @Override
    public void onShow(DialogInterface dialog) {
        getDialog().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    }
});

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