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]() ...