mrroboaat
mrroboaat

Reputation: 5692

DialogFragment and force to show keyboard

I have a problem with my DialogFragment. So to create my view, I use the method described on the android blog. Here is my 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;
}

If I use onCreateView(), it works but I would like create an AlterDialog and to do this, I have the following code :

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

If I comment the code from onCreateView(), the app works but I can't force the keyboard to be shown and if I uncomment onCreateView(), I get a crash. Here is the stack trace :

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

So my question ==> Can I use the AlertDialog and show the keyboard when the dialog appears ?

Upvotes: 51

Views: 23891

Answers (6)

VasyaV
VasyaV

Reputation: 136

For some reason nothing worked for me other than this along with myEditText.requestFocus() in onCreateView:

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

Upvotes: 0

CoolMind
CoolMind

Reputation: 28837

If you want to show a keyboard after a short delay, you should use another method. Solutions with onActivityCreated and onCreateDialog work right, but for instant keyboard showing. If you have EditText, you should open the keyboard over it, not over a dialog. See pictures at https://stackoverflow.com/a/65007148/2914140.

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
}

Upvotes: 1

Garfield
Garfield

Reputation: 158

Use "SOFT_INPUT_STATE_ALWAYS_VISIBLE" instead of "SOFT_INPUT_STATE_VISIBLE" either in onActivityCreated or onCreateDialog method.

Upvotes: 16

SqueezyMo
SqueezyMo

Reputation: 1726

Watch out for the setLayout() call if you use it. It took me a while to realize that it may override your window's attributes. After wrapping it into a handler, the accepted solution worked for me.

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

Upvotes: 8

Purgarcita
Purgarcita

Reputation: 325

The answer of tyczj does not work for me.

The solution was, inside onCreateDialog

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

In the end, the code would be like this

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

Upvotes: 21

tyczj
tyczj

Reputation: 73916

override onActivityCreated in your dialogfragment and put getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE); in there

Upvotes: 137

Related Questions