使用FragmentTransaction与DialogFragment

14

我创建了一个DialogFragment,通过此技术显示为对话框。

现在它已经启动,在弹出窗口中的用户交互后,我想要向此对话框中滑入另一个片段。我试图通过FragmentTransaction.add()来实现这一点,其中我将其指定为此布局中的一个容器的ID。此时我收到以下错误:

java.lang.IllegalArgumentException: No view found for id 0x7f09013f for fragment <fragmentClassThatIWasPushingIn>
作为一个快速的测试,我尝试将它推到对话框外部但在主后备活动中的容器ID上,这样做很好用。
DialogFragments及其容器ID是否存在不允许FragmentTransactions的情况?
作为一个临时措施,我已经告诉我的事务隐藏当前的DialogFragment并显示这个新的片段,但是动画/显示有点令人不适,所以我真的想解决这个问题。
谢谢
4个回答

17

当一个DialogFragmentDialog的形式显示时,它实际上不是一个在容器视图中的真正的Fragment,而是一个没有容器的Fragment,基本上是一个Dialog的包装器。

因此,不能在FragmentDialog内显示一个Fragment。如果您真的想这样做,我认为最好的方法是创建一个新的Activity,将其样式设置为Dialog,然后您可以将Fragments添加到其中。


这个是正确的。然而,DialogFragment可以通过setShowsDialog(false)强制作为一个Fragment来使用。请查看我的答案。 - macieksk

3

alexanderblom指出DialogFragment可以作为对话框,但是通过使用setShowsDialog(false);可以让其充当Fragment。

最终以下内容对我有用:

文件: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>

文件 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();
                }
            });
        }

1

实际上,在onCreateView方法中可以看到容器。您可以使用容器来创建视图。

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

看起来FragmentManager无法获取容器。

这可能是一个bug吗?


1

使用 commitAllowingStateLoss() 显示 DialogFragment

DialogFragment.show(FragmentManager manager, String tag) 方法没有选项可以在允许状态丢失的情况下显示对话框。这有点奇怪和不一致,因为有一个 DialogFragment.dismissAllowingStateLoss() 方法。

但是您可以手动提交 DialogFragment 事务,或创建一个类似以下的辅助方法:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接