Using FragmentTransaction with a DialogFragment

2019-03-15 18:48发布

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

3条回答
再贱就再见
2楼-- · 2019-03-15 19:25

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.

查看更多
何必那么认真
3楼-- · 2019-03-15 19:32

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?

查看更多
萌系小妹纸
4楼-- · 2019-03-15 19:33

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();
                }
            });
        }
查看更多
登录 后发表回答