14

So I've created a DialogFragment that is shown as a dialog via this technique

Now that it's launched and upon a user interaction within this popup I want to slide in another fragment to this dialog. I'm trying to do this via FragmentTransaction.add() where I give it the id of one of the containers in this layout. At this point I get:

java.lang.IllegalArgumentException: No view found for id 0x7f09013f for fragment <fragmentClassThatIWasPushingIn>

As a quick test, I tried to push it onto a container id not in the dialog but within the main backing activity and that worked just fine.

Is there something about DialogFragments and its container ids that does not allow for FragmentTransactions?

As a stopgap I've told my transaction to hide the current DialogFragment and show this new fragment, but the animation/display is a little jarring so I'd really like to sort this issue out.

Thanks

Programmer Bruce
  • 64,977
  • 7
  • 99
  • 97
Joey
  • 652
  • 1
  • 7
  • 15

4 Answers4

17

When a DialogFragment is shown as a Dialog it is not actually a real Fragment in a container view. It is a container-less Fragment which is basically a wrapper of a Dialog.

So no, you can not show a Fragment inside a FragmentDialog. If you really want to do this I think the best way would to create a new Activity styled as a Dialog which you can then add Fragments too.

alexanderblom
  • 8,632
  • 6
  • 34
  • 40
  • This is correct. However DialogFragment can be forced to act as a Fragment with setShowsDialog(false);. Check my answer. – macieksk Mar 06 '14 at 11:18
3

alexanderblom is right that DialogFragment acts as a Dialog, however it can be made to act as a Fragment with setShowsDialog(false);

In the end the following worked for me:

File: res/layout/wifidirect_dialog_wifidirect:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/dialog_wifidirect_layout">

    <LinearLayout
        android:id="@+id/frag_container"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:orientation="vertical" >

            <!-- This is replaced during runtime -->
            <RelativeLayout
                android:id="@+id/frag_list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="top" >
            </RelativeLayout>
    </LinearLayout>

    <!-- The Cancel Button -->
    <View
    android:layout_width="fill_parent"
    android:layout_height="1dp"
    android:layout_marginBottom="0dp"
    android:background="?android:attr/dividerVertical" />
    <Button
         android:id="@+id/dialog_wifidirect_cancel"
         style="?android:attr/buttonBarButtonStyle"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="@string/cancel"/>         
</LinearLayout>

File src/.../WifiDirectDialog.java:

public class WiFiDirectDialog extends DialogFragment  {
        public static final String TAG = "WifiDirectDialog";
        public static final String DEVICE_LIST_FRAGMENT_TAG = "WIFIDIRECT_DEVICE_LIST_FRAGMENT";


        public static WiFiDirectDialog newInstance(){                 
             WiFiDirectDialog wDialog = new WiFiDirectDialog();
             //We want this Dialog to be a Fragment in fact,
             //otherwise there are problems with showing another fragment, the DeviceListFragment
             wDialog.setShowsDialog(false);
             //wDialog.setStyle(SherlockDialogFragment.STYLE_NORMAL,android.R.style.Theme_Holo_Light_Dialog);
             //We don't want to recreate the instance every time user rotates the phone
             wDialog.setRetainInstance(true);
             //Don't close the dialog when touched outside
             wDialog.setCancelable(false);
             return wDialog;
        }


        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.v(TAG,"onCreateView");

            View view = inflater.inflate(R.layout.wifidirect_dialog_wifidirect,container, false);

            //Log.v(TAG,"FragmentTransaction started");            
            ListFragment listFragment = new YourListFragment();

            FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
            transaction.addToBackStack(DEVICE_LIST_FRAGMENT_TAG)
                .replace(R.id.frag_list,deviceListFragment,DEVICE_LIST_FRAGMENT_TAG)
                .commit();
            //Log.v(TAG,"FragmentTransaction finished");

            return view;
        };

        @Override
        public void onActivityCreated(Bundle savedInstanceState){
            Log.v(TAG,"onActivityCreated");
            super.onActivityCreated(savedInstanceState);

            Dialog dialog = getDialog();
            dialog.setTitle(R.string.wifidirect_dialog_title);

            // Set button listeners etc...///
            Button cancelButton = (Button) view.findViewById(R.id.dialog_wifidirect_cancel);
            cancelButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {                
                    dismiss();
                }
            });
        }
macieksk
  • 365
  • 3
  • 10
1

Display a DialogFragment with commitAllowingStateLoss()

The DialogFragment.show(FragmentManager manager, String tag) doesn’t have an option to show the dialog while allowing state-loss. It’s a bit strange and inconsistent, because there is a DialogFragment.dismissAllowingStateLoss().

But you can always commit the DialogFragment transaction manually, or create a helper method like this:

public static void showDialogAllowingStateLoss(FragmentManager fragmentManager, DialogFragment dialogFragment, String tag) {
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.add(dialogFragment, tag);
ft.commitAllowingStateLoss();
}
1

there actualy is a container as you can see in the onCreateView method. You use the container to create your view.

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle icicle) {
    Log.d(TAG, "onCreateView");
    View v = inflater
            .inflate(R.layout.move_folder_dialog, container, false);

It seems like the FragmentManager is not able to get the container.

Could this be a bug?

Michiel
  • 66
  • 5