1

How does one handle button clicks in a Dialog fragment. I would like to run method in fragment once a dialog button is clicked, the example given in dev docs works for activities but not fragments.

MyAlertDialog

class MyAlertDialog : DialogFragment() {
    
    var listener: MyListener

    interface MyListener {
        onPositiveClick(dialog: DialogFragment)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        try {
            listener = context as MyListener
        } catch (e: ClassCastException) {

            throw ClassCastException((context.toString() + " must implement MyDailogListener")
        }
    }

    override fun onCreateDialog(savedInstanceState:Bundle?): Dialog {
        return activity?.let {
            val builder = AlertDialog.Builder(it)
            builder.setMessage("Do you want to reset the score.")
                .setPositiveButton("Confirm",
                    DialogInterface.OnClickListener { dialog, id ->
                        ...
                    })
            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }
}

MyFragment

class MyFragment : Fragment(), MyAlertDialog.MyListener {

    ...

    fun launchAlertDialog() {
        val dailog = MyAlertDialog().also {
            it.show(requireActivity().supportFragmentManager, "DialogInfoFragment")
        } 
    }

    override fun onDialogPostiveCLick(dialog: DialogFragment) {
        Log.i(TAG, "Listener returns a postive click")
    }
}
helper
  • 100
  • 6
  • Is this the correct compilable code? I am asking because you have the listener type name everywhere differently. MyDialogListener, MyAlertDialogListener , MyListener – Dinkar Kumar May 04 '21 at 01:33
  • @dinkar_kumar thanks, I was going back and forth between an example online and one I was practicing with. – helper May 04 '21 at 05:53

1 Answers1

1

The DialogFragment is launched from the activity not from the fragment despite being called in the fragment. Linking the interface this way will only work if you are connecting to an activity.

If you are only updating data, you could pass the ViewModel into the DialogFragment through the constructor.

Fragment

fun launchAlertDialog() {
    val fragment = MyFragment(viewModel)
    fragment.show(requireActivity().supportFragmentManager, "MyAlertDialog")
}

DialogFragment

class MyAlertDialog(val viewModel: MainViewModel) : DialogFragment() {
    overrideOnCreateDialog(savedInstanceState: Bundle?): Dialog {
        return activity?.let {
            val builder = AlertDialog.Builder(it)
            builder.setMessage(...)
                .setPositiveButton("My Text", DialogInterface.OnClickListener { dialog, id -> 
                    viewModel.updateMyData()
                })
            builder.create()
        } 
    } ?: throw IllegalStateException("Activity cannot be null")

}

You could also use this approach here to run a function in the Fragment. https://stackoverflow.com/a/65116644/3943340

Keep in mind that setTargetFragment is now deprecated, as of API 28(could be wrong on the API).

Shawn
  • 1,222
  • 1
  • 18
  • 41