Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding Fragments to a layout

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>
like image 527
coreno Avatar asked Feb 10 '12 14:02

coreno


People also ask

What object is used to add a fragment to a layout?

To declaratively add a fragment to your activity layout's XML, use a FragmentContainerView element. The android:name attribute specifies the class name of the Fragment to instantiate.

What is a fragment layout?

A Fragment represents a reusable portion of your app's UI. A fragment defines and manages its own layout, has its own lifecycle, and can handle its own input events. Fragments cannot live on their own--they must be hosted by an activity or another fragment.

How do you create a fragment?

To create a blank Fragment , expand app > java in Project: Android view, select the folder containing the Java code for your app, and choose File > New > Fragment > Fragment (Blank).

How add and remove fragments?

Use replace() to replace an existing fragment in a container with an instance of a new fragment class that you provide. Calling replace() is equivalent to calling remove() with a fragment in a container and adding a new fragment to that same container. transaction. commit();


2 Answers

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:

View fragment = inflater.inflate(R.layout.selector, container);

to

View fragment = inflater.inflate(R.layout.selector, null);

or even better

View fragment = inflater.inflate(R.layout.selector, container, false);

Don't forget to do the same in your DetailsFragment too.

like image 57
Alex Curran Avatar answered Oct 15 '22 19:10

Alex Curran


When you inflate a layout inside the getView method of a Fragment, you must use the next inflate method: inflater.inflate(R.layout.details, container, false);

The key is the third parameter. It must be false not to attach the inflated layout to the container, because the system already done it. If it is true or is not indicated a redundant group view is created.

like image 36
Dani Avatar answered Oct 15 '22 20:10

Dani