Ezzy Wachira
Ezzy Wachira

Reputation: 390

Getting an error when launching a material date picker from a fragment android

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)

Upvotes: 0

Views: 1218

Answers (2)

laalto
laalto

Reputation: 152817

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

Upvotes: 3

Ezzy Wachira
Ezzy Wachira

Reputation: 390

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.

Upvotes: 0

Related Questions