Fragment getArguments() returns null - android

I have a Fragment which has a TabHost as the root layout as follows...
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="#+id/tab_1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<!-- More FrameLayouts here - each are placeholders for Fragments -->
</FrameLayout>
</LinearLayout>
</TabHost>
The code to create / update each Fragment for the tab content is as follows...
private void updateTab(String tabId, int placeholder) {
FragmentManager fm = getFragmentManager();
if (fm.findFragmentByTag(tabId) == null) {
Bundle arguments = new Bundle();
arguments.putInt("current_day", mCurrentTab);
EpgEventListFragment fragment = new EpgEventListFragment();
fragment.setArguments(arguments);
fm.beginTransaction()
.replace(placeholder, new EpgEventListFragment(), tabId)
.commit();
}
}
In the onCreate(...) method of the EpgEventListFragment I then try to get the arguments Bundle but I always get null doing the following...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle arguments = getArguments();
if (arguments == null)
Toast.makeText(getActivity(), "Arguments is NULL", Toast.LENGTH_LONG).show();
else
mCurrentDay = getArguments().getInt("current_day", 0);
...
}
What am I missing here? I also tried getArguments() in onAttach(...) but I still got null. I'm new to using Fragments so I'm hoping there's a simple reason but I haven't come up with anything when searching.

I'm thinking this has to do with your problem:
fm.beginTransaction()
.replace(placeholder, new EpgEventListFragment(), tabId)
.commit();
You're making a new Fragment (that doesn't have arguments since it's been freshly instantiated).
Instead try
Fragment fragment = new EpgEventListFragment();
fragment.setArguments(arguments);
fm.beginTransaction()
.replace(placeholder, fragment, tabId)
.commit();

Related

How to add another fragment on the existing fragment?

I am trying to create tab layout with fragments. When i add another fragment on item click it should show another fragment above it. I am unable to get the goal. Fragment just goes above the existing one but both the fragments content are visible. Please don't throw the link towards any developer page for explanation.
Here is my code
home_activity.xml
<TabHost
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TabWidget
android:id="#android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</TabWidget>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/tab1"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.example.tabsfragment.School_Fragment" >
</fragment>
<fragment
android:id="#+id/tab2"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.example.tabsfragment.Sports_Fragment" >
</fragment>
</FrameLayout>
</LinearLayout>
</TabHost>
Home_Activity.java
public class Home_Activity extends FragmentActivity {
TabHost mHost;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home_activity);
mHost = (TabHost) findViewById(android.R.id.tabhost);
mHost.setup();
TabSpec schoolSpec = mHost.newTabSpec("School").setIndicator("School")
.setContent(R.id.tab1);
mHost.addTab(schoolSpec);
TabSpec sportSpec = mHost.newTabSpec("Sports").setIndicator("Sportss")
.setContent(R.id.tab2);
mHost.addTab(sportSpec);
mHost.setCurrentTab(1);
}
entertainment.xml
<FrameLayout
android:id="#+id/frameContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</FrameLayout>
I am adding another fragment on list_item_click inside Sports_Fragment
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
FragmentTransaction ft = getFragmentManager().beginTransaction();
Entertainment_Fragment enFragment = new Entertainment_Fragment();
ft.replace(android.R.id.tabcontent, enFragment);
ft.commit();
}
Here is the snapshot :
Any ideas/help with explanation would be highly appreciated.
Thanks!!
First of all, I think it's worth mentioning...
"You cannot replace a fragment defined statically in the layout file. You can only replace fragments that you added dynamically via a FragmentTransaction"
Please see
Android: can't replace one fragment with another
How can I show a new Fragment within a single tab?
Here's the solution.
In home_activity.xml, you should leave your tabcontent empty.
<FrameLayout
android:id="#+id/tabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
Your Home_Activity
private FragmentTabHost mHost;
public void changeFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
EntertainmentFragment enFragment = new EntertainmentFragment();
ft.replace(R.id.tabcontent, enFragment);
ft.commit();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mHost.setup(this, getSupportFragmentManager(), R.id.tabcontent);
mHost.addTab(mHost.newTabSpec("School")
.setIndicator("School"), SchoolFragment.class, null);
mHost.addTab(mHost.newTabSpec("Sport")
.setIndicator("Sport"), SportsFragment.class, null);
}
In your onIemClick (Sports_Fragment), add this
MainActivity mainAct = (MainActivity)getActivity();
mainAct.changeFragment();
My full project, which is based on your code, is here.
I haven't had a chance to really check why TabHost doesn't work when I tested your code.
But FragmentTabHost works fine for me.
Edit: To fix the overlap problem, you can set OnTabChangeListener:
mHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
#Override
public void onTabChanged(String tabId) {
// TODO Auto-generated method stub
if (tabId.equalsIgnoreCase("School")) {
Log.v(TAG, "school");
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
schoolFrag = new SchoolFragment();
ft.replace(R.id.tabcontent, schoolFrag);
ft.commit();
}
if (tabId.equalsIgnoreCase("Sport")) {
Log.v(TAG, "Sport");
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
SportsFragment sportFrag = new SportsFragment();
ft.replace(R.id.tabcontent, sportFrag);
ft.commit();
}
}
});
About the backpress, you can try
ft.addToBackStack(null);

Android Fragment, No view found for id inside TabHost

I have a simple Android application with tabs set up using Tabhost and Fragments. On one of the tab pages, the fragment is a listview. What I want to do is when a user clicks on one of the items of the list view, open up a new view with more specific information based on the item clicked but preserving it so that the tabs are still there.
My approach is when a user clicks on a item in the listview, a new fragment is created and then from my main FragmentActivity class that owns all of these fragments and handles the tabbing logic, it will detach the currently shown fragment and add this "new" (singleStationListItem) fragment. The issue I am encountering is that I cannot add my new fragment to the fragmentTransaction with the R.id.realtabcontent and thus, it is not properly added. I get:
03-21 10:50:01.862: E/FragmentManager(1136): No view found for id 0x1010000 (android:attr/theme) for fragment singleStationListItem{40d090a0 #2 id=0x1010000}
where R.id.realtabcontent = 0x01010000;
I can attach it without the Id, but then users are not able to go back ( call addtobackstash() ). I have searched for this errors but other solutions do not relate to tabhost and I seem to do what is required, like call setContextView(...) in onCreate() to the xml file of the layout that includes the framelayout tag that I am trying to attach my fragment to. I can add my tab fragments to the R.id.realtabcontent without a problem. Does anyone know what could be causing my error and how I can fix it?
Note: I follow this tutorial for getting my tabs working. My code is very similar.
http://thepseudocoder.wordpress.com/2011/10/04/android-tabs-the-fragment-way/
My Code:
activiy_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_body"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TabHost
android:id="#android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0"
android:padding="5dp" />
<FrameLayout
android:id="#+android:id/realtabcontent" <--id that I want to set to
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="-4dp"
android:layout_weight="0"
android:orientation="horizontal" />
</LinearLayout>
</TabHost>
</LinearLayout>
main_activity.java //parts from my fragment activity class
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Step 1: Inflate layout
setContentView(R.layout.activity_main);
// Step 2: Setup TabHost
initialiseTabHost(savedInstanceState);
if (savedInstanceState != null) {
mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); //set the tab as per the saved state
}
}
public void onTabChanged(String tag) { //handles tab changes
TabInfo newTab = (TabInfo) this.mapTabInfo.get(tag);
if (mLastTab != newTab) {
FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
if (mLastTab != null) {
if (mLastTab.fragment != null) {
ft.detach(mLastTab.fragment);
}
}
if (newTab != null) {
if (newTab.fragment == null) {
newTab.fragment = Fragment.instantiate(this,
newTab.clss.getName(), newTab.args);
ft.add(R.id.realtabcontent, newTab.fragment, newTab.tag); //note it uses the R.id.realtabcontent without any issues here
} else {
ft.attach(newTab.fragment);
}
}
Log.d("fragment manager in activity: ", "" + ft.isEmpty());
mLastTab = newTab;
ft.commit();
this.getSupportFragmentManager().executePendingTransactions();
Log.d("ft ID: ", ft.toString());
}
}
//This is the callback function inside the listview fragment. I created an interface and it is overwritten in here as suggested by the Android SDK guide
public void onStationSelected(String station) {
FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
ft.addToBackStack(null);
ft.addToBackStack(null);
//create argument for new fragment that will be created
Bundle b = new Bundle();
b.putString("station", station);
Fragment displayStationInfo = Fragment.instantiate(this, singleStationListItem.class.getName(), b);
Fragment cur = getSupportFragmentManager().findFragmentById(R.id.realtabcontent);
ft.detach(cur);
ft.add(R.id.realtabcontent, displayStationInfo); <-- this line causes the error
ft.commit();
this.getSupportFragmentManager().executePendingTransactions();
}
singleStationListItem.java is here
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle b = this.getArguments();
getActivity().setContentView(R.layout.single_station_item_view);
TextView txtStation = (TextView) getActivity().findViewById(R.id.station_label);
String station = b.getString("station");
// displaying selected product name
Log.d(TAG, "passed in station information: " + station);
txtStation.setText(station);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = (LinearLayout)inflater.inflate(R.layout.single_station_item_view, container, false);
return v;
}
Any help would be greatly appreciated.
I realize this question was asked a while ago, I am posting an answer for others that may come across this question.
As far as I know, there is no Android id of 'realtabcontent'. In your XML, remove the 'android' part of your id for the FrameLayout.
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
The complete XML code posted on the developer documentation is as follows:
<android.support.v4.app.FragmentTabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="#android:id/tabs"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"/>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0"/>
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
Good luck and happy coding!

Adding ListFragment dynamically on android

I am trying to make an android layout where I have ListFragment on the left of the screen that contains menu entries and then an area to the right of the ListFragment where I can programmatically load in different fragments based on the entry selected on the left. So I started off by making an xml layout file that has a horizontal linear layout which contains two frame layouts. My thought was that I could load my fragments into the frame layouts.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="0dp"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/fragment_container_left"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="30"/>
<FrameLayout
android:id="#+id/fragment_container_right"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="70"/>
</LinearLayout>
Then in my MainViewActivity class in the onCreate method I add a list fragment to the left container, and a list fragment to the right container.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menu_items);
if(findViewById(R.id.fragment_container_left) != null) {
if(savedInstanceState == null){
MenuListFragment menuListFragment = new MenuListFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_container_left, menuListFragment);
ft.commit();
}
}
if(findViewById(R.id.fragment_container_right) != null) {
if(savedInstanceState == null){
MoveListFragment moveListFragment = new MoveListFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_container_right, moveListFragment);
ft.commit();
}
}
}
So then the onCreate method of the MenuListFragment is:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(ArrayAdapter.createFromResource(getActivity().getApplicationContext(),
R.array.menu_items, R.layout.main_menu_item));
}
And then the onCreate method of the MoveListFragment is:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] items = { "move 1", "move 2", "move 3", "move 4" };
setListAdapter(new ArrayAdapter<String>(getActivity(), R.layout.move_list_items, items));
}
and here is the main_menu_item xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:padding="6dp"
android:id="#+id/main_menu_item"/>
and move_list_items xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:padding="6dp"
android:id="#+id/move_list_item"/>
When I run this code, I do not get any errors of any kind, but nothing but a white background shows up on the screen. I do not understand what I am doing wrong.
Calling findViewById(R.id.fragment_container_left) will give you the FrameLayout, not the fragment, which obviously will never be null. You should check whether the respective fragment already exists using findFragmentById:
if(getFragmentManager().findFragmentById(R.id.fragment_container_left) == null) {
MenuListFragment menuListFragment = new MenuListFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_container_left, menuListFragment);
ft.commit();
}
As another heads up, you can link the the content fragment with the list fragment using setTargetFragment on the list fragment. This will automatically reconnect the fragments should the fragments be recreated.

How to create multiple fragments programmatically?

I am trying to show multiple fragments on the one screen by creating them programmatically. I am able to do this no problem by including each fragment into the activities layout file. However when I try and do it programmatically Im confused.This is what I have so far for two fragments on a screen.
Main Class:
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentOne one = new FragmentOne();
FragmentTwo two = new FragmentTwo();
FragmentThree three = new FragmentThree();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.imOne, one, "fragmentone");
ft.add(R.id.imTwo, two, "fragmenttwo");
ft.add(R.id.imThree, three, "fragmenthree");
ft.commit();
}
}
Fragment One:
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.frag_one, container, false);
return view;
}
}
Fragment Two:
public class FragmentTwo extends Fragment{
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.frag_two, container, false);
return view;
}
}
The layout files for my two fragment classes just contain a simple TextView.
And then the activity_main.xml layout file for my main class:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/imOne"
android:name="com.david.twofragexample.FragmentOne"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
<FrameLayout
android:id="#+id/imTwo"
android:name="com.david.twofragexample.FragmentTwo"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
<FrameLayout
android:id="#+id/imThree"
android:name="com.david.twofragexample.FragmentThree"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
When I try and do it programatically I get confused as to what should be in my activity_main.xml file. So from the Android Developer Guide(http://developer.android.com/guide/components/fragments.html) it says to use
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
So when I add this code to my onCreate method what changes do I have to make to my activity_main.xml file to do this programmatically?I don't see where R.id.fragment_container comes from. How can I determine where on the screen my new fragment will go?Thanks
EDIT: I am developing this on a tablet and not a phone.This has now been solved and the above code will add three fragments programmatically.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/list"
android:name="com.david.twofragexample.FragmentOne"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
<FrameLayout
android:id="#+id/viewer"
android:name="com.david.twofragexample.FragmentTwo"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
In your Activity:
FragmentOne one = new FragmentOne();
FragmentTwo two = new FragmentTwo();
fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.list, one, "fragmentone").commit();
fm.beginTransaction().replace(R.id.viewer, two, "fragmenttwo").commit();
I suggest you study this:
http://developer.android.com/reference/android/app/Fragment.html
and fully understand the fragment lifecycle, etc. The way I show is quick and dirty, but not neccesarilly best.
As I don't have higher enough reps to comment yet, I will just leave the information here -- the way Rafael T suggested does work nicely, although I also had my doubt at the first place.
1) Define your xml like this:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
2) Add each fragment into the same slot:
View box = v.findViewById(R.id.container);
FragmentTransaction ft = getFragmentManager().beginTransaction();
for (String catalog : mCatalogs) {
Fragment fragment = HighlightedProductFragment.newInstance(catalog);
ft.add(R.id.container, fragment, catalog);
}
ft.commit();
Thanks for the solution for this tricky requirement.
Try it like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
as your activity_main.xml
You asked yourself the right question: where is the id fragment_container, and the answer was: nowhere. >ou also set your layout to horizontal, which makes it very likely, that added Views will be kind of 'out of screen'

Dynamically add fragment into fragment

I haven't been able to find a way how to dynamically add fragment into existing dynamically added fragment. Do you know, if it is possible?
I am generating fragments this way:
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xact = fragMgr.beginTransaction();
if(null == fragMgr.findFragmentByTag(FRAG1_TAG)) {
xact.add(10101010, new DateTime(), FRAG1_TAG);
}
if(null == fragMgr.findFragmentByTag(FRAG4_TAG)) {
xact.add(7777, new loginForm(), FRAG4_TAG);
}
xact.commit();
How to add into FRAG4_TAG fragment another one?
Edit2:
I hard coded it's id to be able to work with it in future (where ll is my linearLayout in XML):
FrameLayout frml4 = (FrameLayout)inflater.inflate(R.layout.frame,null);
frml4.setId(7777);
frml4.setBackgroundColor(Color.YELLOW);
ll.addView(frml4);
I assume the problem that you are running into is that there is not an inflated view to add the fragment to because the original fragment, FRAG4_TAG, has not been inflated before you are trying to add it.
You can pass enough information to FRAG4_TAG in the Arguments to let it know that it should create and add a fragment (or what all fragments you need it to have) to itself during it's onCreateView, after the view has been inflated...
The layout for the activity...
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="MyActivity"/>
<LinearLayout
android:orientation="vertical"
android:id="#+id/main_frag_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
The Activity...
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragOne = new MyFragment();
Bundle arguments = new Bundle();
arguments.putBoolean("shouldYouCreateAChildFragment", true);
fragOne.setArguments(arguments);
ft.add(R.id.main_frag_container, fragOne);
ft.commit();
}
}
The layout for the fragment...
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="20dp">
<TextView
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Some fragment"/>
<LinearLayout
android:orientation="vertical"
android:id="#+id/frag_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
The fragment...
public class MyFragment extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.frag_layout, container, false);
boolean shouldCreateChild = getArguments().getBoolean("shouldYouCreateAChildFragment");
if (shouldCreateChild) {
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
fm.beginTransaction();
Fragment fragTwo = new MyFragment();
Bundle arguments = new Bundle();
arguments.putBoolean("shouldYouCreateAChildFragment", false);
fragTwo.setArguments(arguments);
ft.add(R.id.frag_container, fragTwo);
ft.commit();
}
return layout;
}
}
This example covers the case where you need to dynamically add fragments to a fragment that HAS NOT already been inflated and added to the hierarchy. Adding a fragment to a fragment that HAS already been inflated and added to the hierarchy is as simple as just specifying the target fragments container that you want to add to by ID like you would normally.
As the documentation states "A fragment must always be embedded in an activity".
So when you add a "sub-fragment" it will always belong to the activity even if you add it within your fragment class. For example if you later decide to remove the containing fragment the sub fragments won't be automatically removed.
When I had to do the same I had to store in a vector the sub fragments and manually remove them in the onDestroy methods of my container fragment.
I think that fragments are not thought to be used like this
You cannot insert Fragments into other Fragments. (At least, not yet)
You can however replace Fragments with other Fragments with FragmentTransaction.replace(containerViewId, Fragment).
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.linear1, new activity()).commit();
}

Categories

Resources