DialogFragment和强制显示键盘

51

我有一个DialogFragment的问题。为了创建视图,我使用了安卓博客上描述的方法。 这是我的DialogFragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View myLayout = inflater.inflate(R.layout.dialog_connect, null);

    edit = (EditText) myLayout.findViewById(R.id.password_edit);
    edit.requestFocus();
    getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);

    return myLayout;
}

如果我使用onCreateView(),它可以工作,但是我想创建一个AlterDialog,为此,我有以下代码:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Inflate and set the layout for the dialog
    // Pass null as the parent view because its going in the dialog layout
    builder
           .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int id) {
                    callback.onYesConnectClick(edit.getText().toString());
                }
            })
            .setNegativeButton(R.string.refuse, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int id) {
                    callback.onNoConnectClick();
                }
            });

    return builder.create();
}

如果我注释掉onCreateView()中的代码,应用程序可以正常运行,但我无法强制显示键盘。如果我取消注释onCreateView(),应用程序会崩溃。 以下是堆栈跟踪:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test/com.test.ProfileActivity_}: android.util.AndroidRuntimeException:     requestFeature() must be called before adding content
AndroidRuntime at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2312)
AndroidRuntime at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2362)
AndroidRuntime at android.app.ActivityThread.access$600(ActivityThread.java:156)
AndroidRuntime at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1250)
AndroidRuntime at android.os.Handler.dispatchMessage(Handler.java:99)
AndroidRuntime at android.os.Looper.loop(Looper.java:137)
AndroidRuntime at android.app.ActivityThread.main(ActivityThread.java:5229)
AndroidRuntime at java.lang.reflect.Method.invokeNative(Native Method)
AndroidRuntime at java.lang.reflect.Method.invoke(Method.java:525)
AndroidRuntime at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
AndroidRuntime at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
AndroidRuntime at dalvik.system.NativeStart.main(Native Method)
AndroidRuntime Caused by: android.util.AndroidRuntimeException: requestFeature() must be called before adding content

所以我的问题是 ==> 当AlertDialog出现时,我能否使用它并显示键盘?

6个回答

137

在你的DialogFragment中重写onActivityCreated,并在其中添加getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);


9
什么鬼?!我找了好久,解决方案却是这么简单!但是有一件事我不明白。我试图在启动对话框的那个活动的清单文件中设置 android:windowSoftInputMode="stateVisible",但它没用... 注:本翻译尽可能保留原文表达方式,但也有做适当调整以符合中文语言习惯的情况。 - mrroboaat
1
谢谢!在StackOverflow上有大约十几个其他的“解决方案”来解决这个问题,但是它们都对我无效...但是这个有效。 - josh2112
1
这似乎是我能找到的所有解决方案中最有效的一个。我很好奇为什么这必须在onActivityCreated中调用,而不是在onResume()中?我真的很想听听一些解释。 - Sean
我尝试了很多方法,但只有这个有效 :O - EpicPandaForce
我有一个DialogFragment,其中包含一个使用此库进行自定义视图膨胀的MaterialSearchView。https://github.com/MiguelCatalan/MaterialSearchView。当从我的DialogFragment启动MaterialSearchView时,我无法让键盘显示出来。 - AdamHurwitz
使用WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE。这个解决方案是有效的,但如果你想延迟显示键盘,它就不起作用了(例如,lifecycleScope.launch { delay(300) dialog?.window?.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE) })。 - CoolMind

21

tyczj的回答对我不起作用。

解决方案是,在onCreateDialog内部进行操作。

Dialog d = builder.create();
d.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
return d;

最终,代码会像这样

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Inflate and set the layout for the dialog
    // Pass null as the parent view because its going in the dialog layout
    builder
           .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int id) {
                    callback.onYesConnectClick(edit.getText().toString());
                }
            })
            .setNegativeButton(R.string.refuse, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int id) {
                    callback.onNoConnectClick();
                }
            });

    Dialog d = builder.create();
        d.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
return d;
}

15
onActivityCreatedonCreateDialog方法中使用"SOFT_INPUT_STATE_ALWAYS_VISIBLE"代替"SOFT_INPUT_STATE_VISIBLE"

1
这对我来说是解决方案,结合Purgarcita在onCreateDialog的解决方案。 - user960914

8

如果你使用setLayout(),请注意它可能会覆盖你的窗口属性。在将其包装成处理程序后,我花了一段时间才意识到这一点,接受的解决方案对我有用。

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    final Dialog dialog = super.onCreateDialog(savedInstanceState);
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

    return dialog;
}

@Override
public void onStart() {
    super.onStart();

    // without a handler, the window sizes itself correctly
    // but the keyboard does not show up
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            getDialog().getWindow().setLayout(DIALOG_WIDTH, DIALOG_HEIGHT);
        }
    });
}

太完美了!setLayout() 函数造成了问题。 - Ibrahim Gharyali

1
如果您想在短暂延迟后显示键盘,则应使用另一种方法。 使用onActivityCreatedonCreateDialog的解决方案是正确的,但用于即时显示键盘。 如果您有EditText,则应该在其上打开键盘,而不是在对话框上。 请参见https://dev59.com/Jl4c5IYBdhLWcg3wn7qj#65007148中的图片。
fun showKeyboard(view: EditText) {
    val imm = view.context.getSystemService(
        Context.INPUT_METHOD_SERVICE) as InputMethodManager?
    imm?.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
}


override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    super.onCreateDialog(savedInstanceState)

    val view = activity?.layoutInflater?.inflate(R.layout.your_layout, null)

    view?.edit_text?.run {
        requestFocus() // Required for showing a keyboard.
        setText("Some text")
        setSelection(text.length)
    }

    val dialogBuilder = MaterialAlertDialogBuilder(requireContext()).apply {
        setView(view)
        // Set message, buttons.
        setCancelable(false)
    }
    val dialog = dialogBuilder.create()

    Handler(Looper.getMainLooper()).postDelayed({
        view?.edit_text?.let { showKeyboard(it) }
    }, 100)
//    Instead of Handler you can use coroutines:
//    lifecycleScope.launch {
//        delay(100)
//        view?.edit_text?.let { showKeyboard(it) }
//    }

    return dialog
}

0

出于某种原因,除了在 onCreateView 中使用 myEditText.requestFocus(),我别无选择。

override fun onStart() {
    dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
    super.onStart()
}

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