动态添加碎片时出现错误 -java.lang.IllegalStateException:

5
我第一次在3.0上工作。 我想要动态地添加片段,但是出现了错误:
10-18 18:29:11.215: ERROR/AndroidRuntime(3550): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

XML代码

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

<ListView
        android:id="@+id/number_list"
        android:layout_width="250dip"
        android:layout_height="match_parent" />

<FrameLayout
        android:id="@+id/the_frag"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

活动

public class FragmentExampleActivity extends Activity implements
    OnItemClickListener {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ListView l = (ListView) findViewById(R.id.number_list);
    ArrayAdapter<String> numbers = new ArrayAdapter<String>(
            getApplicationContext(), android.R.layout.simple_list_item_1,
            new String[] { "one", "two", "three", "four", "five", "six" });
    l.setAdapter(numbers);
    l.setOnItemClickListener(this);
}

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    Fragment f = new FragmentExample();

    FragmentTransaction ft = getFragmentManager().beginTransaction();       
    ft.replace(R.id.the_frag, f);
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    ft.addToBackStack(null);
    ft.commit();

}
}


public class FragmentExample extends Fragment {
private int nAndroids=1;

public FragmentExample() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved) {
    int n;

    View l = inflater.inflate(R.layout.textlay,container);
    TextView tv = (TextView) l.findViewById(R.id.textView1);
    tv.setText("value "+nAndroids);

    return l;
}

}

请帮我指出哪里出了问题 :(
4个回答

19

不要使用

View l = inflater.inflate(R.layout.textlay,container);

你应该使用

View l = inflater.inflate(R.layout.textlay, container, false);

或者另外一种选择

View l = inflater.inflate(R.layout.textlay, null );

我强烈建议您使用带有三个参数的inflate版本。Android仅将容器用于布局参数。将第三个参数设置为false可防止将textlay添加到container中并解决您的问题。


2
容器应该仅用于布局参数,而不是在充气期间使用。 - Spidy
1
在所有出现相同错误的问题中,这个解决方案很有帮助。我认为错误信息没什么用。非常感谢! - IAmGroot

4
如果在onCreateView()中,您想要重用视图,则可以处理onDestroyView()。
@Override
public void onDestroyView() {
    super.onDestroyView();
    if (view != null) {
        ViewGroup parentViewGroup = (ViewGroup) view.getParent();
        if (parentViewGroup != null) {
            parentViewGroup.removeAllViews();
        }
    }
}

3
或者你可以使用第三个参数,并将其传递为false。
inflater.inflate(R.layout.sample_fragment, container,false);

这意味着不要将当前视图附加到根视图。

0
以下代码可以解决多个问题:
public static View contentView;

public static class MenuCardFrontFragment extends Fragment {
    public MenuCardFrontFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        try
        {
            LinearLayout frontLayout = (LinearLayout)inflater.inflate(R.layout.content_card, container, false);
            // modify layout if necessary
            return contentView = frontLayout;
        } catch (InflateException e) {
            return contentView;
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (contentView != null) {
            ViewGroup parentViewGroup = (ViewGroup) contentView.getParent();
            if (parentViewGroup != null) {
                parentViewGroup.removeAllViews();
            }
        }
    }
}

1. 如果片段(Fragment)带有动画,并且用户在动画未完成时被强制重复执行动画,例如:在菜单片段的动画完成之前按两次菜单按钮。(这个问题已经通过 user2764384 的 onDestroyView 得到解决) 2. 如果调用 inflate 方法时指定了容器以获取容器布局,则会出现问题,因为在第二次发生时,旧容器已经有一个视图。因此,如果发生异常,它将被捕获并返回旧视图 contentView。

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