I am trying to make my app more tablet-friendly, and so I’m trying to learn fragments. I want the typical two-pane layout, where the left side is the “navigation”, and you click on one of the elements, and it changes the fragment on the right.
I can duplicate the tutorials that use a ListFragment for the left, and if you click on one of them, it updates the “details” fragment on the right.
I’ve tried the best I can to duplicate that code, and just use a LinearLayout, with buttons for the left side, so that if a button is clicked, it loads the appropriate fragment on the right, but it’s not working.
When I commit the FragmentTransaction, I get java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. What is the child’s parent, and why do I have to call removeView on it?
I’m trying to load the fragment into a FrameLayout, but I’ve also just tried replacing another Fragment in the layout, and still get the error.
Ideally I want the left fragment to take up the whole screen until a button is pressed that requires a fragment to come in from the left, but one problem at a time I suppose.
Code
Main Activity
public class FragmentExample2Activity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
SelectorFragment (Left side)
public class SelectorFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View fragment = inflater.inflate(R.layout.selector, container);
Button button1 = (Button) fragment.findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
getFragmentManager().beginTransaction().replace(R.id.detail_holder, new DetailsFragment(), "stuff").commit();
}
});
return fragment;
}
}
DetailsFragment
public class DetailsFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
return inflater.inflate(R.layout.details, container);
}
}
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<fragment class="com.coreno.testfragment.SelectorFragment"
android:id="@+id/select"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
/>
<fragment class="com.coreno.testfragment.DetailsFragment"
android:id="@+id/detail_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
/>
<!--
<FrameLayout
android:id="@+id/detail_holder"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="2"
/>
-->
</LinearLayout>
When you inflate a layout xml file, don’t specify the parent view. It sounds very counter-intuitive to not specify where you’re putting this inflated view but it works.
So, for example, in your SelectorFragment change the line:
to
or even better
Don’t forget to do the same in your DetailsFragment too.