Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble returning date from DatePickerDialog fragment when using Navigation Controller

I am trying to return a date selected from my DatePickerDialog. I know there are a few questions about this here on SO and I am sure I have checked for those in my code and I still can't get the date back into my fragment that calls the DatePickerDialog.

I am using the Navigation confonent to show the dialog, could that be what is causing the issue?

Here is my DatePickerDialog:

class DatePickerFragment : DialogFragment(), DatePickerDialog.OnDateSetListener {

    private var onDateSetListener: DatePickerDialog.OnDateSetListener? = null

    fun setListeningActivity(listener: DatePickerDialog.OnDateSetListener) {
        onDateSetListener = listener
    }

    override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) {
        onDateSetListener?.onDateSet(view,year, month, dayOfMonth)
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        // Use the current date as the default date in the picker
        val c = Calendar.getInstance()
        val year = c.get(Calendar.YEAR)
        val month = c.get(Calendar.MONTH)
        val day = c.get(Calendar.DAY_OF_MONTH)

        // Create a new instance of DatePickerDialog and return it
        return DatePickerDialog(context, this, year, month, day)
    }
}

Relevant code from the fragment calling the Datepicker:

private fun showDatePicker(hasFocus: Boolean, view: View) {
    Log.i(FRAGMENT_NAME, "Has focus $hasFocus")
    val fragment = DatePickerFragment()
    fragment.setListeningActivity(this)
    if (hasFocus) {
        Navigation.findNavController(view).navigate(R.id.datePickerFragment)
    }
}

override fun onDateSet(view: DatePicker, year: Int, month: Int, day: Int) {
    Log.i(FRAGMENT_NAME, "Date received: $year-$month-$day")
    fragmentView.dateOfBirthField.editText?.setText("$year-$month-$day")
}

This is how I am calling the showDatePicker method:

fragmentView.dateOfBirthField.editText?.setOnFocusChangeListener { _, hasFocus -> showDatePicker(hasFocus, fragmentView) }

Question: How do I get the date back into the Fragment that calls the DatePickerDialog. I do not want to have the DatePickerDialog as an internal class to the class that calls it.

like image 606
DrkStr Avatar asked Apr 16 '26 12:04

DrkStr


1 Answers

Best way for fragment data passing is livedata with viewmodel, when you are using navigation architecture component.

Step-1 Create ViewModel which will hold your selectedDate. Create the instance of LiveData so that you can observe the changes.

class SharedViewModel: ViewModel() {
    val selectedDate: MutableLiveData<String> = MutableLiveData()
}

Step-2 Get the instance of SharedViewModel and update selectedDate variable to notify it's observers. (In DatePickerFragment)

override fun onDateSet(view: DatePicker, year: Int, month: Int, day: Int) {
    val viewModel = ViewModelProviders.of(activity!!)[SharedViewModel::class.java]
    viewModel.selectedDate.value = "$year $month $day"
}

Step-3 Get the instance of SharedViewModel where, you want to observe the changes. (In our case, from where datePickerFragment invoked.)

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)

    ViewModelProviders.of(activity!!)[SharedViewModel::class.java]
            .selectedDate
            .observe(activity!!, Observer { dateOfBirthField.editText.setText(it) })
}

If you are using androidx artifact. Then you may need follwoing dependency.

implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0-alpha01'
like image 96
Moinkhan Avatar answered Apr 18 '26 11:04

Moinkhan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!