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.
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'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With