在 DialogFragment 中使用 FragmentManager 和 FragmentTransaction

Posted

技术标签:

【中文标题】在 DialogFragment 中使用 FragmentManager 和 FragmentTransaction【英文标题】:Using FragmentManager and FragmentTransaction in a DialogFragment 【发布时间】:2012-06-14 11:04:13 【问题描述】:

问题的要点是:我正在尝试从 FragmentActivity 启动 DialogFragment。这个 DialogFragment 的视图包含一个 FrameLayout,我想用 Fragment 填充它。基本上,FragmentActivity 启动 DialogFragment,然后 DialogFragment 用 Fragment 填充它的 FrameLayout。我已经在互联网上搜索了教程,并且拼凑了一些(在我看来)应该有用的东西。但是,无论我尝试什么,我都会不断出错。这是我目前所拥有的:

这是我的 FragmentActivity 的布局(文件名为“activity_interact”):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/activity" >
<Button
        android:id="@+id/btnLaunchDialog"
        style="@style/btn" />

这是我的 DialogFragment 的布局(文件名为“dialog_overview”):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/dialog" >
<FrameLayout
    android:id="@+id/frameDisplay"
    style="@style/frame" />

这是我的 Fragment 的布局(文件名为“fragment_stats”):

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/table" >
<TableRow style="@style/table" >
    <TextView
        style="@style/display"
        android:gravity="right"
        android:text="@string/textStr" />
</TableRow>

这是我的 FragmentActivity 的 java 代码:

public class ActivityInteract extends FragmentActivity implements
    OnClickListener 

Button btnLaunchDialog;

@Override
protected void onCreate(Bundle b) 
    super.onCreate(b);
    setContentView(R.layout.activity_interact);
    btnLaunchDialog = (Button) findViewById(R.id.btnLaunchDialog);
    btnLaunchDialog.setOnClickListener(this);


public void onClick(View v) 
    switch (v.getId()) 
        case R.id.btnLaunchDialog:
            FragmentManager fm = getSupportFragmentManager();
            DialogOverview dialogOverview = new DialogOverview();
            dialogOverview.show(fm, "dialog_overview");
            break;
    

这是我的 DialogFragment 的代码:

public class DialogOverview extends DialogFragment implements OnClickListener 

public DialogOverview() 


@Override
public View onCreateView(LayoutInflater li, ViewGroup vg, Bundle b) 
    View view = li.inflate(R.layout.dialog_overview, vg);
    FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.add(R.id.frameDisplay, new FragmentStats());
    ft.commit();
    return view;

这是我的 Fragment 的代码:

public class FragmentStats extends Fragment 

@Override
public View onCreateView(LayoutInflater li, ViewGroup vg, Bundle b) 
    View view = li.inflate(R.layout.fragment_stats, vg);
    return view;

最后,这是 logcat 错误:

06-11 10:07:29.382: E/AndroidRuntime(30013): java.lang.IllegalArgumentException: No view found for id 0x7f060003 for fragment FragmentStats4169c928 #1 id=0x7f060003

我可以看到它是说我对 Fragment 没有看法,但我有……(或者我有吗?)我在这里迷路了,任何帮助将不胜感激。另外,我是否以正确的方式进行此操作?重用 FragmentManager 会更有效吗? (即将它从 FragmentActivity 传递到 DialogFragment)

更新:我删除了将 Fragment 加载到 DialogFragment 中的代码,现在 DialogFragment 显示没有问题。所以很明显(正如 logcat 错误所暗示的那样)我的 Fragment 本身有问题......但是,它与我在互联网上看到的示例相匹配。这让我想知道:以这种方式嵌套片段是否存在问题?显示 Fragment 的 DialogFragment 的 FragmentActivity 让我想打趣说“我们不能再深入了”,但我不知道。我可以嵌套更多的片段吗?

【问题讨论】:

有人吗?我看不出有什么问题……我可能遗漏了一些非常明显的东西…… 所以我搜索了更多内容并偶然发现了这篇文章:Using FragmentTransaction with a DialogFragment 显然,Dialog is a container-less view。本质上,当您尝试将片段加载到对话框中时,它会寻找容器......它没有找到......而不是说“嘿,没有一个愚蠢的对话框容器!”它说您的片段没有视图。我相信声明您不能将片段添加到对话框片段将是包含在文档中的好信息。无论如何,问题解决了。我会关闭这个问题,但我是新人...... 您可以在 DialogFragment 中使用嵌套片段。看我的回答。 【参考方案1】:

实际上,您可以将嵌套的fragment 添加到DialogFragment,但它不能基于包装的Dialog。

不要覆盖onCreateDialog,而是膨胀包含将使用onCreateView 中的Fragment 的ViewGroup 的视图。

这样做的结果是您不能使用包装 AlertDialog 的 DialogFragment - 因此,如果您需要正面和负面按钮,您需要在内容视图中手动创建它们。

另外,请记住,您不能在 XML 中设置片段。您需要在 XML 中声明容器视图并以编程方式执行片段事务。

公共类 MyDialogFragment 扩展 DialogFragment [...]

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 



    final View view = inflater.inflate(R.layout.dialog_layout, container);

    if (savedInstanceState == null) 
        final ChildFragment fragment = [...];
        getChildFragmentManager()
                .beginTransaction()
                .replace(R.id.fragment_container, fragment)
                .commit();
    

    return view;
    

【讨论】:

以上是关于在 DialogFragment 中使用 FragmentManager 和 FragmentTransaction的主要内容,如果未能解决你的问题,请参考以下文章

android camera2连拍

在 DialogFragment 中使用 FragmentManager 和 FragmentTransaction

为啥要使用 DialogFragment?

DialogFragment 优于 AlertDialog [重复]

在 show() 之前获取 DialogFragment 子类中的父活动

DialogFragment.getDialog 返回 null