Reputation: 684
I'm working on 3.0 for the first time. I want to add fragments dynamically , but its shown error:-
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 code
<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" />
Activity
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;
}
}
Plz put some light on , where i'm going wrong :(
Upvotes: 5
Views: 3592
Reputation: 157437
Instead of using
View l = inflater.inflate(R.layout.textlay,container);
you should use
View l = inflater.inflate(R.layout.textlay, container, false);
or alternatively
View l = inflater.inflate(R.layout.textlay, null );
I strongly suggest you to use, the version of inflate
which takes three parameters. Android use the container only for the layout's params purpose. Passing false
as third parameter, prevents the addition of textlay
, to container
and fixes your issue
Upvotes: 19
Reputation: 24205
The following solves multiple problems:
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();
}
}
}
}
If fragments shows with animation and user forced to repeat the animation before it's over. ex: pressing menu button twice before the menu fragment finishes animating and appear. (this got solved by the onDestryView from user2764384)
If inflate method called with specifying the container to get container lay outing. it looks like that cases a problem because at the 2nd time that happened the old container already have a view. so if that exception happen it will be caught and returns the old view contentView.
Upvotes: 0
Reputation: 41
if in onCreateView() , you want to reuse view , then you can deal with onDestroyView()
@Override
public void onDestroyView() {
super.onDestroyView();
if (view != null) {
ViewGroup parentViewGroup = (ViewGroup) view.getParent();
if (parentViewGroup != null) {
parentViewGroup.removeAllViews();
}
}
}
Upvotes: 4
Reputation: 6170
or you can use third argument and pass it as a false.
inflater.inflate(R.layout.sample_fragment, container,false);
it means that don't attach current view to root.
Upvotes: 3