Programmatically Working with Android Fragments

by | Jun 17, 2013

I had another great class of soon-to-be Android engineers in my class last week.  Some came a very long way to learn Android.  Baris made his first trip to the U.S. all the way from Turkey and Joshua and Doug came up from Mason City, Iowa.  Thanks for making the long trip guys and thanks to all my students (local and long distance) last week for your attendance and participation.

During last week’s class, my students learned that Fragments (since Android 3) can be used to organize the display of information in Activities, especially those that have to deal with multiple device form factors (i.e. screen size, screen density, rotation, etc.).  Fragments also provide a means to create reusable portions of UI display/functionality.

Add/Remove Fragments Programmatically

An Activity’s layout can include Fragments as shown below.

<LinearLayout
  android:layout_width="wrap_content"
  android:layout_height="match_parent">
  <fragment
    android:id="@+id/headFrag"
    android:name="com.intertech.HeaderFrag"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"/>
  <fragment
    android:id="@+id/bodyFrag"
    android:name="com.intertech.BodyFrag"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"/>
</LinearLayout>

However, as with View components, Fragments can be programmatically added to or removed from a containing View in the Activity without being defined in the Activity’s layout.  To programmatically add or remove a Fragment, you will need the FragmentManager and FragmentTransaction instances.  Simply stated and per the Android documentation, a FragmentManager manages the fragments in an Activity.  Obtain the FragmentManager by calling getFragmentManager( ) in an Activity.  A collection of Fragment changes made to an Activity that are to be done at the same time are created inside of a transaction.  Transactions for Fragment changes to an Activity are established and committed (or undone/rolledback) via the FragmentTransaction instance.  Get or “start” the FragmentTransaction direct from the FragmentManager instance by calling beginTransaction( ).  The method commit( ) is used to asynchronously invoke the Fragment changes on the Activity.

FragmentManager fragmentManager = getFragmentManager ();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction ();
// work here to change Activity fragments (add, remove, etc.).  Example here of adding.
fragmentTransaction.add (R.id.myFrame, myFrag);
fragmentTransaction.commit ();

Adding and removing fragments is only a portion of the changes that can be accomplished with the FragmentManager/FragmentTransaction.  You can also replace one Fragment with another, show or hide a Fragment (actually this is to show or hide the visible View components tied to the Fragment as Fragments of themselves have no direct visible representation), attach or detach a Fragment, and more. See the API documentation for more details, but the list below outlines a number of the important methods on FragmentTransaction.

  • add(containerViewId, fragment_instance):  Add a fragment to the Activity state with the identifier of the container this Fragment is to be placed in and the Fragment to be added.
  • attach(fragment):  Re-attach the specified Fragment from the UI after it had previously been deatched (with call to detach).
  • detach(fragment):  Detach the given Fragment from the UI (the Fragment is removed from the UI, however its state is still being actively managed by the FragmentManager).
  • hide(fragment):  Hides an existing Fragment. Only relevant for Fragments whose views have been added to a container.  Causes the views to be hidden.
  • remove(fragment):  Remove an existing Fragment.
    replace(containerViewId, fragment):  Replace an existing fragment that was added to a container. This is essentially the same as calling remove(fragment) for all currently added fragments that were added with the same containerViewId and then add(containerViewId, Fragment).
  • show(fragment):  Shows a previously hidden Fragment.

 

Programmatic Fragment Add/Remove Example

As a simple example, I have provided a demo application that adds and removes a Fragment with the push of a button on an Activity. 

Frag Demo StartFrag Demo End

When the Add Fragment button is pushed, a simple Fragment containing only a TextView (background in orange) displaying the current time in milliseconds is added to the LinearLayout of the current Activity.  When the Remove Fragment button is pushed, the last Fragment added is removed from the LinearLayout of the Activity.  I put the bulk of the Fragment adding/removing demonstration work in the Activity’s (MyActivity.java) onClick listener method associated to the two buttons.

if(v.equals(addButton)){
  FragmentManagerfragmentManager=getFragmentManager();
  FragmentTransactionfragmentTransaction=fragmentManager.beginTransaction();
  myFrag=newMyFrag();
  myFrag.setSpecialText("Fragtime:"+System.currentTimeMillis());
  myFragList.add(myFrag);
  fragmentTransaction.add(R.id.myFrame,myFrag);
  fragmentTransaction.commit();
}
else {
  if((myFragList.size()-1)>=0){
    FragmentManagerfragmentManager=getFragmentManager();
    FragmentTransactionfragmentTransaction=fragmentManager.beginTransaction();
    MyFraglastFrag=myFragList.get(myFragList.size()-1);
    fragmentTransaction.remove(lastFrag);
    myFragList.remove(lastFrag);
    fragmentTransaction.commit();
  }
}

Using the Fragment Back Stack
A record of all Fragment transactions is kept for each Activity.  More precisely, the FragmentManager retains a back stack of all FragmentTransactions for the Activity.  When used properly, this allows the user to hit the device’s back button to remove previously added Fragments (not unlike how the back button removes an Activity).

In order to manage and track each FragmentTransaction, call addToBackStack( ) on each FragmentTransaction as it is added to the Activity.  The optional parameter to the method is the name to be used for this transaction.

FragmentManagerfragmentManager=getFragmentManager();
FragmentTransactionfragmentTransaction=fragmentManager.beginTransaction();
myFrag=newMyFrag();
myFrag.setSpecialText("Fragtime:"+System.currentTimeMillis());
myFragList.add(myFrag);
fragmentTransaction.add(R.id.myFrame,myFrag);
fragmentTransaction.addToBackStack("myFrag");
fragmentTransaction.commit();

Programmatically, you can also pop from the back stack too.  In fact, as part of any programmatic remove call in my example, you may want to pop the last transaction from the stack.

fragmentManager.popBackStack ();

Wrap Up
My thanks again to my class of Android students for there questions.