I'm trying to launch an Material date picker from a fragment and I'm getting this error
java.lang.IllegalStateException: Fragment MaterialDatePicker{6058a76} (da2fbbc0-ee9f-4536-85f7-3942c18a1087) not attached to an activity.
My Fragment
@AndroidEntryPoint
class ReportFragment : Fragment() {
private var _binding: FragmentReportBinding? = null
private val binding get() = _binding!!
private var stDate: Long? = null
private var ndDate: Long? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentReportBinding.inflate(inflater, container, false)
setUpUi()
return binding.root
}
private fun setUpUi() {
with(binding) {
startDate.setOnClickListener {
showDatePicker(
getString(R.string.select_start_date),
selectedStartDate,
DateType.START_DATE
)
}
}
}
private fun showDatePicker(dateCategory: String, textView: TextView, dateType: DateType) {
val datePicker = MaterialDatePicker.Builder.datePicker().apply {
setTitleText(dateCategory)
setInputMode(MaterialDatePicker.INPUT_MODE_CALENDAR)
setSelection(MaterialDatePicker.todayInUtcMilliseconds())
}.build()
datePicker.apply {
show(requireActivity().supportFragmentManager, "DATE_PICKER")
addOnPositiveButtonClickListener {
val date = this.headerText
textView.text = date
when (dateType) {
DateType.START_DATE -> stDate = it
DateType.END_DATE -> ndDate = it
}
}
}
}
}
enum class DateType {
START_DATE,
END_DATE
}
This is the error I'm getting
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.reachafrika.reachafrikapay, PID: 15162
java.lang.IllegalStateException: Fragment MaterialDatePicker{6058a76} (da2fbbc0-ee9f-4536-85f7-3942c18a1087) not attached to an activity.
at androidx.fragment.app.Fragment.requireActivity(Fragment.java:928)
at com.reachafrika.reachafrikapay.presentation.ui.fragments.reports.ReportFragment.showDatePicker(ReportFragment.kt:137)
at com.reachafrika.reachafrikapay.presentation.ui.fragments.reports.ReportFragment.setUpUi$lambda-4$lambda-1(ReportFragment.kt:71)
at com.reachafrika.reachafrikapay.presentation.ui.fragments.reports.ReportFragment.$r8$lambda$5X7432cB-iIkf15NUD-AuzGqT3E(Unknown Source:0)
at com.reachafrika.reachafrikapay.presentation.ui.fragments.reports.ReportFragment$$ExternalSyntheticLambda3.onClick(Unknown Source:4)
at android.view.View.performClick(View.java:7184)
at android.view.View.performClickInternal(View.java:7157)
at android.view.View.access$3500(View.java:821)
at android.view.View$PerformClick.run(View.java:27660)
at android.os.Handler.handleCallback(Handler.java:914)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:225)
at android.app.ActivityThread.main(ActivityThread.java:7563)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:994)
CodePudding user response:
I replaced the
datePicker.apply {
show(requireActivity() ...
with the following code
show([email protected]().supportFragmentManager, "DATE_PICKER")
and it worked
Here is the full body function
private fun showDatePicker(dateCategory: String, textView: TextView, dateType: DateType) {
val datePicker = MaterialDatePicker.Builder.datePicker().apply {
setTitleText(dateCategory)
setInputMode(MaterialDatePicker.INPUT_MODE_CALENDAR)
setSelection(MaterialDatePicker.todayInUtcMilliseconds())
}.build()
datePicker.apply {
show([email protected]().supportFragmentManager, "DATE_PICKER")
addOnPositiveButtonClickListener {
val date = this.headerText
textView.text = date
when (dateType) {
DateType.START_DATE -> stDate = it
DateType.END_DATE -> ndDate = it
}
}
}
}
As the suggestion was given above. that apply changes the receiver i.e. this, and the receiver here has requireActivity() defined too, so it resolves first.
CodePudding user response:
datePicker.apply {
show(requireActivity() ...
Here you are calling requireActivity() on the datePicker that is not attached to any activity yet. Remember that apply changes the receiver i.e. this, and the receiver here has requireActivity() defined too, so it resolves first.
You likely want to call requireActivity() on the calling fragment, as in
datePicker.apply {
show([email protected]() ...
