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++;
jpihl
  • 7,941
  • 3
  • 37
  • 50
Zapnologica
  • 22,170
  • 44
  • 158
  • 253

2 Answers2

109

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

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Philipp Jahoda
  • 50,880
  • 24
  • 180
  • 187
  • 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 ? – Zapnologica Aug 18 '13 at 08:13
  • This will absolutely work. @Zapnologica Look on SO to find how to generate unique ids. But, it shouldn't be a problem to use something like `647589`. – Vikram Aug 18 '13 at 08:20
  • Just choose whatever Integer you want as the id :) – Philipp Jahoda Aug 18 '13 at 08:24
  • 4
    http://stackoverflow.com/questions/8460680/how-can-i-assign-an-id-to-a-view-programmatically >> Good Link – Zapnologica Aug 18 '13 at 08:31
  • @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. – Zapnologica Aug 18 '13 at 10:43
  • Are you setting the id for your rowlayout? try this line: fragmentsLayout.addView(rowLayout); before the fragmenttransaction – Philipp Jahoda Aug 18 '13 at 11:32
  • @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. – Zapnologica Aug 18 '13 at 16:24
  • Allright, give me a second I will create a project and try it out and then post the solution here. – Philipp Jahoda Aug 18 '13 at 16:57
  • Updated the answer and posted the working code. I tested it on emulator and on my device. – Philipp Jahoda Aug 18 '13 at 17:13
  • @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. – Zapnologica Aug 18 '13 at 22:56
  • 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. – Philipp Jahoda Aug 19 '13 at 06:37
  • @Phil you dont think it has something to do with not using supportv4? cause i am using plain `import android.app.Fragment;` – Zapnologica Aug 19 '13 at 07:18
  • Just changed it all to support library and it still does the same. its so weird. – Zapnologica Aug 19 '13 at 07:43
  • 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() – Philipp Jahoda Aug 19 '13 at 08:11
  • 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 it – Zapnologica Aug 19 '13 at 08:13
  • 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 ;) – Philipp Jahoda Aug 19 '13 at 08:15
  • 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. – Zapnologica Aug 19 '13 at 11:13
  • @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? – Zapnologica Aug 19 '13 at 16:36
  • But root layout is not generated programmatically – Aznix Feb 11 '15 at 13:09
  • 11
    I'd recommend using `View.generateViewId()` to generate a view ID. – Jeremy Wiebe Aug 30 '16 at 19:54
  • Once screen is rotated. I got duplicate of fragments. – Sithideth Bouasavanh Jan 02 '18 at 12:36
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);
        }
Farmaker
  • 2,700
  • 11
  • 16