material-components / material-components-android

Modular and customizable Material Design UI components for Android
Apache License 2.0
16.35k stars 3.07k forks source link

[MaterialDatePicker] does not work as Embedded DialogFragment #660

Open cpeppas opened 5 years ago

cpeppas commented 5 years ago

Description: My aim is to create a MaterialDatePicker dialogfragment but instead of displaying as a dialog to use it as a normal embedded fragment

Expected behavior: The datepicker to work normally as embedded fragment

Actual behavior: App crashes with the following tracktrace

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6077)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
     Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
        at android.view.ViewGroup.addViewInner(ViewGroup.java:4454)
        at android.view.ViewGroup.addView(ViewGroup.java:4295)
        at android.view.ViewGroup.addView(ViewGroup.java:4235)
        at android.view.ViewGroup.addView(ViewGroup.java:4208)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:887)
        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
        at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
        at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManagerImpl.java:2663)
        at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManagerImpl.java:2613)
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:246)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:542)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1248)
        at android.app.Activity.performStart(Activity.java:6679)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2609)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6077) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) 

Source code: Using the catalog demo app from this repository

//Activity code snippet from onCreate
supportFragmentManager.beginTransaction()
                    .replace(R.id.container, getPickerFragment())
                    .commit()

private fun getPickerFragment(): DialogFragment {
        val fragment = MaterialDatePicker.Builder
                .datePicker()
                .setTheme(resolveOrThrow(this, R.attr.materialCalendarFullscreenTheme))
                .build()
        fragment.showsDialog = false
        return fragment
    }

Android API version: minSkd 21 - targetSdk 28

Material Library version: Material Android Library version 1.1.0-beta01

Device: Emulator Nexus6 API:24 x86

herrbert74 commented 4 years ago

I ran into this as well. Business requirement is to have a registration flow with sliding animation, and the second screen is date of birth. It has to have a customized header with flow progress indicator, so a dialog won't do, neither as full screen nor modal. The current screen uses a Windows Phone style picker from years ago, so I wanted to replace it. What's infuriating me is, that as the name suggests, a fragment should be used as a part of a screen, instead it's used as a full screen or as a dialog nowadays. Things are shifted. It seems to me this will never be solved as pickers are dialogs, so we need another custom solution. Blimey!

UKDeveloper99 commented 3 years ago

A DialogFragment is designed to be used as a Dialog or a Fragment. It's ridiculous that you can't just insert the fullscreen version or the dialog in to a view as a fragment. Makes zero sense.

barantes commented 8 months ago

This feature request should not be ignored by Google, since it contradicts their own documentation found here: https://developer.android.com/develop/ui/views/components/pickers

That page says:

We recommend you use DialogFragment to host each time or date picker. The DialogFragment manages the dialog lifecycle for you and lets you display pickers in different layout configurations, such as in a basic dialog on handsets or as an embedded part of the layout on large screens.