Fragments Overview
Fragment
                     components
                     allow you to organize your application code so that it is
                     easier to
                     support
                     different sized devices.
                    
               Fragments
                     are components with their own lifecycle and their own user interface.
                     They can be defined via layout files or via coding.
                    
               Fragments
                     always
                     run in the context of an
                     Activity. If an
                     Activity
                     is stopped its
                     Fragments
                     will also be stopped; if an
                     Activity
                     is destroyed its
                     Fragments
                     will also get destroyed.
                    
               If a
Fragment
                     component
                     is defined in an XML layout file, the
                     android:name
                     attribute points to the
                     Fragments
                     class.
                    
               The base class for
Fragments
                     is
                     android.app.Fragment. For special purposes you can also use more special classes, like
                     ListFragment
                     or
                     DialogFragment.
                    
               The onCreateView() method is called by Android once the
Fragment
                     should create its user interface. Here you can inflate an layout. The
                     onStart() method is called once the
                         Fragment
                         gets visible.
                        
                    
               Fragments
                     can be dynamically added and removed from an
                     Activity
                     via
                     Fragment
                     transactions. This will add the action to the history stack of the
                     Activity, i.e. this will allow to revert the
                     Fragment
                     changes in the
                     Activity
                     via the back button.
                    
               Fragments
                     make it easy to re-use components
                     in different layouts, e.g. you
                     can
                     build
                     single-pane layouts for handsets
                     (phones) and multi-pane
                     layouts
                     for
                     tablets.
                    
               This is not limited to tablets; for example you can use
Fragments
                     also to support different layout for landscape and portrait
                     orientation. But as tablets offer significantly more space you
                     typically include more views into the layout and
                     Fragments
                     makes that
                     easier.
                    
               The typical example is a list of items in an activity. On a tablet you see the details immediately on the same screen on the right hand side if you click on item. On a handset you jump to a new detail screen. The following discussion will assume that you have two
Fragments
                     (main and
                     detail) but you can also have more. We will also
                     have one
                     main
                     activity and one detailed activity. On a tablet the main
                     activity
                     contains both
                     Fragments
                     in its layout, on a handheld it only
                     contains the main fragment.
                    
               To check for an fragment you can use the FragmentManager.
DetailFragment fragment = (DetailFragment) getFragmentManager(). findFragmentById(R.id.detail_frag); if (fragment==null || ! fragment.isInLayout()) { // start new Activity } else { fragment.update(...); }
To create different layouts with
Fragments
                     you can:
                  
                     
               - 
                        Use one activity, which displays two
                                 
Fragmentsfor tablets and only one on handsets devices. In this case you would switch theFragmentsin the activity whenever necessary. This requires that the fragment is not declared in the layout file as suchFragmentscannot be removed during runtime. It also requires an update of the action bar if the action bar status depends on the fragment.
 - 
                        Use separate activities to host each fragment on a handset.
                                 For
                                 example, when the tablet UI uses two
                                 
Fragmentsin an activity, use the same activity for handsets, but supply an alternative layout that includes just one fragment. When you need to switchFragments, start another activity that hosts the other fragment.
 
The second approach is the most flexible and in general preferable way of using
Fragments. In this case the main activity
                     checks if the detail fragment is
                     available in the layout. If the
                     detailed fragment is there, the main
                     activity tells the fragment that
                     is should update itself. If the
                     detail
                     fragment is not available the
                     main activity starts the detailed
                     activity.
                    
               It is good practice that
Fragments
                     do not manipulate each other. For this purpose a
                     Fragment
                     typically implements an interface to get new data from its
                     host
                     Activity.
                    
               
The following tutorial demonstrates how to use
                     
In portrait mode
In landscape mode
Fragments. The entry
                     Activity
                     (called
                     MainActivity
                     of our application)
                     will use different layouts for portrait and for
                     landscape mode.
                    
               In portrait mode
MainActivity
                     will show one Fragment with a list of names. If the user touches an
                     item in the list, a second
                     Activity
                     called
                     DetailActivity
                     will start and show the selected text.
                    
               In landscape mode
MainActivity
                     will show two
                     Fragments. The first is again the
                     Fragments
                     which shows the list of names. The second
                     Fragment
                     shows the text of the current selected item. This is similar to the
                     portrait mode, but the whole information will be shown on one screen.
                    
               
Create a new project
                     
de.vogella.android.fragments
                     with an
                     Activity
                     called
                     MainActivity.
                    
               
Create or change the following layout files in the
                     "res/layout/" folder.
                    
               
First create the following file called "details.xml". This layout will be used by the
Change the existing
First create the following file called "details.xml". This layout will be used by the
DetailFragment.
                    
               <?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="vertical" > <TextView android:id="@+id/detailsText" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center_horizontal|center_vertical" android:layout_marginTop="20dip" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" android:textSize="30dip" /> </LinearLayout>
Change the existing
main.xml file. This layout
                     will be used by
                     MainActivity
                     in landscape mode and shows two
                     Fragments.
                    
               <?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" > <fragment android:id="@+id/listFragment" android:layout_width="150dip" android:layout_height="match_parent" android:layout_marginTop="?android:attr/actionBarSize" class="de.vogella.android.fragments.ListFragment" ></fragment> <fragment android:id="@+id/detailFragment" android:layout_width="match_parent" android:layout_height="match_parent" class="de.vogella.android.fragments.DetailFragment" > <!-- Preview: layout=@layout/details --> </fragment> </LinearLayout>
Create now the
                     
Create the
Fragment
                     classes. Create the
                     ListFragment
                     class.
                    
               package de.vogella.android.fragments; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; public class ListFragment extends android.app.ListFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); String[] values = new String[] { "Android", "iPhone", "WindowsMobile", "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2" }; ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, values); setListAdapter(adapter); } @Override public void onListItemClick(ListView l, View v, int position, long id) { String item = (String) getListAdapter().getItem(position); DetailFragment fragment = (DetailFragment) getFragmentManager() .findFragmentById(R.id.detailFragment); if (fragment != null && fragment.isInLayout()) { fragment.setText(item); } else { Intent intent = new Intent(getActivity().getApplicationContext(), DetailActivity.class); intent.putExtra("value", item); startActivity(intent); } } }
Create the
DetailFragment
                     class.
                    
               package de.vogella.android.fragments; import android.app.Fragment; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; public class DetailFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e("Test", "hello"); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.details, container, false); return view; } public void setText(String item) { TextView view = (TextView) getView().findViewById(R.id.detailsText); view.setText(item); } }
We want that Android uses a different main.xml file in portrait
                     model
                     then in landscape mode.
                    
               
For this reason create the "res/layout-port" folder.
In portrait mode Android will check the "layout-port" folder for fitting layout files. Only if we would not have a
Therefore create the following
Also create the "details_activity_layout.xml" layout file. This layout will be used in the
For this reason create the "res/layout-port" folder.
In portrait mode Android will check the "layout-port" folder for fitting layout files. Only if we would not have a
main.xml file in
                     "layout-port", Android
                     would
                     check the "layout" folder.
                    
               Therefore create the following
main.xml layout file in
                     "res/layout-port".
                    
               <?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" > <fragment android:id="@+id/listFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="?android:attr/actionBarSize" class="de.vogella.android.fragments.ListFragment" /> </LinearLayout>
Also create the "details_activity_layout.xml" layout file. This layout will be used in the
DetailActivity
                     which is only used in portrait mode. Please note that we could have
                     create this file also in the "layout" folder, but as it is only used
                     in portrait mode it is best practise to place it into this folder.
                    
               <?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="vertical" > <fragment android:id="@+id/detailFragment" android:layout_width="match_parent" android:layout_height="match_parent" class="de.vogella.android.fragments.DetailFragment" /> </LinearLayout>
Create a new
                     
Activity
                     called
                     DetailActivity
                     with the following class.
                    
               package de.vogella.android.fragments; import android.app.Activity; import android.content.res.Configuration; import android.os.Bundle; import android.widget.TextView; public class DetailActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Need to check if Activity has been switched to landscape mode // If yes, finished and go back to the start Activity if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { finish(); return; } setContentView(R.layout.details_activity_layout); Bundle extras = getIntent().getExtras(); if (extras != null) { String s = extras.getString("value"); TextView view = (TextView) findViewById(R.id.detailsText); view.setText(s); } } }
MainActivity
                     will remain unmodified.
                    
               package de.vogella.android.fragments; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity {/** Called when the activity is first created. */@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } }
Run your example. If you run the application in portrait mode you
                     should see only one
                     
The
Fragment. Use Ctrl+F11 to switch the orientation. In horizontal mode you
                     should
                     see two
                     Fragments. If you select an item in portrait mode a new
                     Activity
                     should get started with the selected item. In horizontal mode your
                     second
                     Fragment
                     should display the select item.ActionBar navigation with Fragments
Fragments can also be used in combination with theActionBar
                 for navigation. For this your main
                 Activity
                 needs to implement a
                 TabListener
                 which is responsible for moving between the tabs.
                
            The
ActionBar
                 allows to add tabs to it via the
                 newTab()
                 method. The following code shows such an
                 Activity. It uses two
                 Fragments, called
                 DetailFragment
                 and
                 ImageFragment. At this point you should be able to create these two
                 Fragments
                 yourself.
                
            package de.vogella.android.fragment; import android.app.ActionBar; import android.app.ActionBar.Tab; import android.app.ActionBar.TabListener; import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.os.Bundle; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // setup action bar for tabs ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); actionBar.setDisplayShowTitleEnabled(false); Tab tab = actionBar .newTab() .setText("First tab") .setTabListener(new MyTabListener<DetailFragment>(this, "artist", DetailFragment.class)); actionBar.addTab(tab); tab = actionBar .newTab() .setText("Second Tab") .setTabListener(new MyTabListener<ImageFragment>(this, "album", ImageFragment.class)); actionBar.addTab(tab); } public static class MyTabListener<T extends Fragment> implements TabListener { private Fragment mFragment; private final Activity mActivity; private final String mTag; private final Class<T> mClass;/** * Constructor used each time a new tab is created. * * @param activity * The host Activity, used to instantiate the fragment * @param tag * The identifier tag for the fragment * @param clz * The fragment's Class, used to instantiate the fragment */public MyTabListener(Activity activity, String tag, Class<T> clz) { mActivity = activity; mTag = tag; mClass = clz; } /* The following are each of the ActionBar.TabListener callbacks */ public void onTabSelected(Tab tab, FragmentTransaction ft) { // Check if the fragment is already initialized if (mFragment == null) { // If not, instantiate and add it to the activity mFragment = Fragment.instantiate(mActivity, mClass.getName()); ft.add(android.R.id.content, mFragment, mTag); } else { // If it exists, simply attach it in order to show it ft.setCustomAnimations(android.R.animator.fade_in, R.animator.animationtest); ft.attach(mFragment); } } public void onTabUnselected(Tab tab, FragmentTransaction ft) { if (mFragment != null) { ft.setCustomAnimations(android.R.animator.fade_in, R.animator.test); ft.detach(mFragment); } } public void onTabReselected(Tab tab, FragmentTransaction ft) { } } }
 (vogella.com) 
cool