How to add a fragment to a programmatically generated layout?
Asked Answered
P

2

62

I have the following code working which generates fragments, but only if I am adding them to a linear layout which exists in my XML file.

LinearLayout fragmentsLayout = (LinearLayout) findViewById(R.id.foodItemActvity_linearLayout_fragments);
FragmentManager fragMan = getFragmentManager();
FragmentTransaction fragTransaction = fragMan.beginTransaction();

Fragment myFrag= new ImageFragment();
fragTransaction.add(R.id.foodItemActvity_linearLayout_fragments, myFrag , "fragment" + fragCount);
fragTransaction.commit();

Now what if I want to add that fragment to a linear layout that does not already exist in the XML file such as

LinearLayout rowLayout = new LinearLayout();

Part 2:

    Fragment frag1 = generateAppropriateFragment(type1);
    Fragment frag2 = generateAppropriateFragment(type2);

    LinearLayout fragmentsLayout = (LinearLayout) findViewById(R.id.foodItemActvity_linearLayout_fragments);
    LinearLayout rowLayout = new LinearLayout(this);
    rowLayout.setId(12345); // add counter to end

    fragmentsLayout.addView(rowLayout);     
    getFragmentManager().beginTransaction().add(rowLayout.getId(), frag1, "fragment_grandchild" + fragCount).commit();
    fragCount++;
    getFragmentManager().beginTransaction().add(rowLayout.getId(), frag2, "fragment_grandchild" + fragCount).commit();
    fragCount++;
Pereyra answered 18/8, 2013 at 7:48 Comment(0)
A
110

At some point, I suppose you will add your programatically created LinearLayout to some root layout that you defined in .xml. This is just a suggestion of mine and probably one of many solutions, but it works: Simply set an ID for the programatically created layout, and add it to the root layout that you defined in .xml, and then use the set ID to add the Fragment.

It could look like this:

LinearLayout rowLayout = new LinearLayout();
rowLayout.setId(whateveryouwantasid);
// add rowLayout to the root layout somewhere here

FragmentManager fragMan = getFragmentManager();
FragmentTransaction fragTransaction = fragMan.beginTransaction();   

Fragment myFrag = new ImageFragment();
fragTransaction.add(rowLayout.getId(), myFrag , "fragment" + fragCount);
fragTransaction.commit();

Simply choose whatever Integer value you want for the ID:

rowLayout.setId(12345);

If you are using the above line of code not just once, it would probably be smart to figure out a way to create unique-IDs, in order to avoid duplicates.

UPDATE:

Here is the full code of how it should be done: (this code is tested and works) I am adding two Fragments to a LinearLayout with horizontal orientation, resulting in the Fragments being aligned next to each other. Please also be aware, that I used a fixed height and width of 200dp, so that one Fragment does not use the full screen as it would with "match_parent".

MainActivity.java:

public class MainActivity extends Activity {

    @SuppressLint("NewApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     

        LinearLayout fragContainer = (LinearLayout) findViewById(R.id.llFragmentContainer);

        LinearLayout ll = new LinearLayout(this);
        ll.setOrientation(LinearLayout.HORIZONTAL);

        ll.setId(12345);

        getFragmentManager().beginTransaction().add(ll.getId(), TestFragment.newInstance("I am frag 1"), "someTag1").commit();
        getFragmentManager().beginTransaction().add(ll.getId(), TestFragment.newInstance("I am frag 2"), "someTag2").commit();

        fragContainer.addView(ll);
    }
}

TestFragment.java:

public class TestFragment extends Fragment {

    public static TestFragment newInstance(String text) {

        TestFragment f = new TestFragment();

        Bundle b = new Bundle();
        b.putString("text", text);
        f.setArguments(b);
        return f;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

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

        ((TextView) v.findViewById(R.id.tvFragText)).setText(getArguments().getString("text"));     
        return v;
    }
}

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rlMain"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="5dp"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <LinearLayout
        android:id="@+id/llFragmentContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:layout_marginTop="19dp"
        android:orientation="vertical" >
    </LinearLayout>
</RelativeLayout>

fragment.xml:

  <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="200dp"
    android:layout_height="200dp" >

    <TextView
        android:id="@+id/tvFragText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="" />

</RelativeLayout>

And this is the result of the above code: (the two Fragments are aligned next to each other) result

Actinomycin answered 18/8, 2013 at 7:59 Comment(21)
That is exactly what I am trying to do!! Only thing is what must I set the id as? Cause it wants an INT and normally in the xml files the id is a string ?Pereyra
This will absolutely work. @Pereyra Look on SO to find how to generate unique ids. But, it shouldn't be a problem to use something like 647589.Bush
Just choose whatever Integer you want as the id :)Actinomycin
#8461180 >> Good LinkPereyra
@Phil I solved the compiling issues, but now it wont display my row layout. Please see my original question i added a part 2 which is my code. it runs but i dont see the two fragments.Pereyra
Are you setting the id for your rowlayout? try this line: fragmentsLayout.addView(rowLayout); before the fragmenttransactionActinomycin
@Phil Yes i am setting its id. And I tried with it before still same thing. It compiles and runs. the fragments on create methods run. but no display. my code displays if I just add the fragment to the FragmentLayout. But not with the row layout.Pereyra
Allright, give me a second I will create a project and try it out and then post the solution here.Actinomycin
Updated the answer and posted the working code. I tested it on emulator and on my device.Actinomycin
@Phil PLease see mt edit to the original post, i updated my code. When i add both fragments then my display is blank, but i can see the space of where the 2 fragments are meant to load. it even gets bigger as the image in the fragment loads. But if I remove the one it works fine.Pereyra
Well maybe there is something wrong with the code inside your fragment, where you inflate. What does generateAppropriateFragment() do? See my updated answer please, I changed the code and now I add two Fragments to the LinearLayout, it still works fine.Actinomycin
@Phil you dont think it has something to do with not using supportv4? cause i am using plain import android.app.Fragment;Pereyra
Just changed it all to support library and it still does the same. its so weird.Pereyra
I dont think so since im also using android.app.Fragment. Please post the code of one of your Fragments and the code of generateAppropriateFragment()Actinomycin
I think my issue is with my layout params, i just changed the linear layout to vertical and it displayed. SO its not persay a fragment issue I must just play around with the settings. @Phil Thanks SO much for your help. Really appreciate itPereyra
Please take a close look at my code and the explanation of it. If you set your Fragments width and height to match_parent, one Fragment will not be displayed. You are welcome ;)Actinomycin
I have still be battling, I can add 2 buttons and a fragment and a variation of those combos to the layout, but i cant add 2 fragments, it just will not work.Pereyra
@Phil Ok i think i have come right. i See you set your fragments widths manually. How can I do it so that each fragment is 50% of the screens width wide?Pereyra
But root layout is not generated programmaticallyBusywork
I'd recommend using View.generateViewId() to generate a view ID.Gailey
Once screen is rotated. I got duplicate of fragments.Emeric
U
0

Below is a working code to add a fragment e.g 3 times to a vertical LinearLayout (xNumberLinear). You can change number 3 with any other number or take a number from a spinner!

for (int i = 0; i < 3; i++) {
            LinearLayout linearDummy = new LinearLayout(getActivity());
            linearDummy.setOrientation(LinearLayout.VERTICAL);
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {

                Toast.makeText(getActivity(), "This function works on newer versions of android", Toast.LENGTH_LONG).show();

            } else {
                linearDummy.setId(View.generateViewId());
            }
            fragmentManager.beginTransaction().add(linearDummy.getId(), new SomeFragment(),"someTag1").commit();

            xNumberLinear.addView(linearDummy);
        }
Unanimous answered 21/9, 2018 at 14:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.