以编程方式将Fragment添加到内部ViewGroup

时间:2013-10-27 10:25:22

标签: android android-layout android-fragments android-fragmentactivity android-dialogfragment

我正在尝试将两个片段添加到以下布局中:

dialog_empty_linear_layout.xml:          

    <LinearLayout
        android:id="@+id/ParentLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:orientation="vertical" >
    </LinearLayout>

</RelativeLayout>

使用以下代码:

setContentView(R.layout.dialog_empty_linear_layout);

int parentViewId = getIntent().getIntExtra(PARENT_VIEW_ID, -1); // == R.id.ParentLayout
if (parentViewId == -1)
    parentViewId = android.R.id.content;

/*
 * Extracting Fragments types
 */
Class<? extends Fragment>[] fragmentTypes = getFragments(); // there are two fragments here!

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
for (Class<? extends Fragment> fragmentType  : fragmentTypes) {
    Fragment fragment = Tools.createNewInstance(fragmentType);
    ft.add(parentViewId, fragment);
}
ft.commitAllowingStateLoss();

执行代码时,我收到以下错误:

引起:java.lang.IllegalStateException:指定的子级已有父级。您必须首先在孩子的父母上调用removeView()。

我很惊讶,因为这是新创建的Activity,包含新创建的片段和新创建的视图 ......

所以我跟踪了堆栈跟踪并检查了我们正在讨论哪个孩子和哪个家长,因为异常没有提供任何关于它的额外信息......

我更惊讶地发现Child是LinearLayout(例如R.ParentLayout),而Parent是包裹它的RelativeLayout。

也许我再次想念显而易见但我想:

ft.add(parentViewId, fragment);

假设将Fragment添加到parentViewId布局,而不是尝试将parentViewId布局添加到其父布局...

另外,如果我使用以下XML,一切正常:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ParentLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

</LinearLayout>

任何见解?

1 个答案:

答案 0 :(得分:0)

嗯,这很有趣......对于那些遇到这种情况的人来说......注意这是非常愚蠢的!

在片段中覆盖此方法:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_id, container);
}

这是愚蠢的事情......

inflater.inflate还有另一个重载:

    return inflater.inflate(R.layout.fragment_id, container, **addToRoot**);

出于某种原因,我希望片段布局添加到容器(不要相信直觉),而不是将容器添加到rootView。直到今天,我一直在将我的所有片段添加到我的根视图中(container == rootView),所以这个问题没有发生,但是一旦容器不是rootView,我必须明确说明addToRoot = false,例如

    return inflater.inflate(R.layout.fragment_id, container, false);

嗯,那就是那个家伙......布尔的愚蠢!