Can't get text from custom dialog using Kotlin

38 Views Asked by At

I have a custom dialog that asks for two text inputs, my goal is to get the text from a textview when the ok option of the dialog is pressed, but so far i can't even access the textView named userName, i can't figure out what i'm doing wrong. with the code below i get this error "@layout/dialog_create_task_type does not contain a declaration with id userName"

This is my DialogFragment:

class TaskTypeCreationDialog : DialogFragment() {

    internal lateinit var listener: TaskTypeCreationDialogListener

    interface TaskTypeCreationDialogListener {
        fun onDialogPositiveClick(dialog: DialogFragment, taskName: String)
        fun onDialogNegativeClick(dialog: DialogFragment)
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return activity?.let {
            val builder = AlertDialog.Builder(it)
            // Get the layout inflater.
            val inflater = requireActivity().layoutInflater;
            val inflatedView = inflater.inflate(R.layout.dialog_create_task_type, null)
            // Inflate and set the layout for the dialog.
            // Pass null as the parent view because it's going in the dialog
            // layout.
            val userName = inflatedView.findViewById<TextView>(R.id.userName)

            builder.setView(inflatedView)
                // Add action buttons.
                .setPositiveButton("ok"
                ) { dialog, id ->
                    listener.onDialogPositiveClick(this, "test")
                    dialog?.cancel()
                }
                .setNegativeButton("cancel"
                ) { dialog, id ->
                    getDialog()?.cancel()
                }
            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        // Verify that the host activity implements the callback interface.
        try {
            // Instantiate the NoticeDialogListener so you can send events to
            // the host.
            listener = context as TaskTypeCreationDialogListener
        } catch (e: ClassCastException) {
            // The activity doesn't implement the interface. Throw exception.
            throw ClassCastException((context.toString() +
                    " must implement NoticeDialogListener"))
        }
    }


}

and this is my xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <EditText
        android:id="@+id/username"
        android:inputType="textEmailAddress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginBottom="4dp"
        android:hint="first text" />
    <EditText
        android:id="@+id/password"
        android:inputType="textPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginBottom="16dp"
        android:fontFamily="sans-serif"
        android:hint="second text"/>
</LinearLayout>

I have also tried to use binding but then it crashes with "java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.CharSequence android.widget.TextView.getText()' on a null object reference " with the code:

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return activity?.let {
            val builder = AlertDialog.Builder(it)
            // Get the layout inflater.
            val inflater = requireActivity().layoutInflater;
            // Inflate and set the layout for the dialog.
            // Pass null as the parent view because it's going in the dialog
            // layout.
            val v = inflater.inflate(R.layout.dialog_create_task_type, null)
            builder.setView(v)
                // Add action buttons.
                .setPositiveButton("ok",
                    DialogInterface.OnClickListener { dialog, id ->
                        val binding = TaskTypeLayoutBinding.bind(v)
                        listener.onDialogPositiveClick(this, binding.userName.text.toString())
                        dialog?.cancel()
                    })
                .setNegativeButton("cancel",
                    DialogInterface.OnClickListener { dialog, id ->
                        getDialog()?.cancel()
                    })
            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }```
1

There are 1 best solutions below

0
sara fernandes On

I have found that my mistake was insisting on getting the TextView on the onCreateDialog(), now that i have moved this logic to the onViewCreated() i have no problem getting the views i need, i'm not sure that my mistake will help anyone but i'll leave my question anyways just in case.

I have made some changes to my code and now it's like this:

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val inflater = requireActivity().layoutInflater;
    val inflatedView = inflater.inflate(R.layout.dialog_create_task_type, null)
    // Inflate and set the layout for the dialog.
    // Pass null as the parent view because it's going in the dialog
    // layout.
return inflatedView
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    binding = DialogCreateTaskTypeBinding.bind(view)
    setupClickListeners(view)
}

private fun setupClickListeners(view: View) {
    val builder = activity?.let { AlertDialog.Builder(it) }
    if (builder != null) {
        builder.setView(view)
            // Add action buttons.
            .setPositiveButton("ok"
            ) { dialog, id ->
                listener.onDialogPositiveClick(this, binding.username.text.toString())
                dialog?.cancel()
            }
            .setNegativeButton("cancel"
            ) { dialog, id ->
                getDialog()?.cancel()
            }
        builder.create()
    }
}