We’re using Honeycomb (Android 3.0, API Level 11) but you can use fragments from Android 1.6 (API Level 4) if you use the support library.
Out with the old: Our activity app
Our existing app is built using activities.
There are three activities:
- MainActivity activity – displays a button. Pressing the button displays a list of contact names in the ContactsList activity
- ContactsList activity – displays a list of contact names. Selecting a contact’s name, displays that contact’s image and name in the DisplayContact activity
- DisplayContact activity - displays the selected contact’s image and name
The MainActivity activity displays a button
Press the button to display the list. Select a list item to display the contact’s image and name
We want to convert this app so that it uses fragments.
Here’s the structure of the fragment version of the app:
In with the new: Our Fragment app
There is one activity and three fragments:
- MainActivity activity – displays the fragments
- ButtonFragment fragment – displays the button. Pressing the button displays a list of contact names in the ContactsListFragment fragment
- ContactsListFragment fragment – displays a list of contact names. Selecting a contact’s name, displays that contact’s image and name in the DisplayContactFragment fragment
- DisplayContactFragment fragment – displays the selected contact’s image and name
Making the change: This is how we’ll make the change
There are three parts to the app:
- A button to display the list
- A list of names to select from
- A display of the selected contact’s image and name
We’ll keep the main activity and put each of the parts into a fragment. Then we’ll display the fragments in the main activity, swopping them in and out as we navigate through the app.
Getting to work: Converting the MainActivity activity
The main activity displays a single button.
Pressing the button starts the ContactsList activity which displays a list of contacts.
The MainActivity activity displays a button
The MainActivity activity consists of the onCreate() method which contains the code for the button:
Get a reference to the button and attach a listener to it in the activity’s onCreate() method
So what’s this?
We get a reference to the button and set an OnClickListener on it to deal with when the user clicks the button.
Clicking the button creates an intent which we use to start the ContactsList activity.
Making the change
Here’s what the code looks like inside the “new” MainActivity activity’s onCreate() method, the one we use for swopping the fragments:
Get a Fragment Manager to interact with the fragments, and then display the fragment
So what’s this?
We’re going to use this activity to “manage” the fragments which we’ll swop as we navigate through the app.
First off, we need to get an instance of the Fragment Manager interface which enables us to interact with the fragments.
Next, we need to check whether we’re showing this activity for the first time or whether it’s being rebuilt (for example when the user changes the screen orientation).
- The savedInstanceState bundle will be empty if we’re creating the activity for the first time. So, we go ahead and create and display the fragment showing the button.
- If we’re rebuilding the activity then we don’t have to do anything
Check out these tutorials if you haven’t already done so:
- Persisting the Activity Instance State
- Fragments Tutorial. Part 1: The basics
We’ve moved: So how do we handle the button clicks?
We move the button’s OnClickListener from the activity to the fragment.
Here’s the code:
The fragment will listen for when the button is clicked
So what’s this?
The fragment’s onCreateView() method inflates the fragment’s layout, creating the User Interface which we need to access the Button view.
We include this code in the fragment’s onViewCreated() method which is executed after the onCreateView() method .
In it we get a reference to the button and set an OnClickListener on it to deal with when the user clicks the button.
Clicking the button calls the showContactsList() method which is found in the MainActivity activity.
Here’s that method:
The showContactsList() method is in the MainActivity activity. It creates and displays the fragment with the list of names
So what’s this?
Clicking the button triggers the onClick() method which executes this method in the MainActivity activity where we create and display the ContactsListFragment fragment.
Note that we call replace() to replace the existing fragment (the button fragment) with this one.
Also note that we include addToBackStack() which ensures that this fragment will be remembered and displayed when the Back button is pressed.
What’s on the list? Handling the list item selections
The MainActivity activity must deal with when the user selects a name from the contacts list. To make this possible, we have to let it implement our custom listener interface which we define in the ContactsListFragment fragment:
Implement the interface for the activity to handle the list item selections in the fragment
So what’s this?
The MainActivity activity implements our custom OnContactsSelectedListener interface to handle the list item selections. We’ll discuss the listener in more detail later when we discuss the ContactsListFragment fragment.
Here’s the listener’s onContactsSelected() method as defined in the MainActivity activity:
The interface method is executed in the activity when an item is selected in the fragment
So what’s this?
Selecting a list item triggers this method. In it we create and display the DisplayContactFragment fragment. This displays the selected contact’s image (well actually a placeholder image) and name.
Note that we use replace() to replace the current fragment with this one.
This method receives the position integer of the selected item as a parameter. We bundle it into the fragment transaction. We’ll use it when creating the fragment to retrieve the selected item’s name.
Note that we also include addToBackStack() which ensures that this fragment will be remembered and displayed when the Back button is pressed.
The ButtonFragment fragment
This fragment displays the button.
We’ve already dealt with the button listener and how the clicks are handled.
There are two additional “parts” of this fragment to briefly touch on:
- The empty constructor which is required for all fragments
- The onCreateView() method. You need to call this method if your fragment includes a User Interface. We have to call it because we have a User Interface, the button. Essentially it inflates the given layout giving us access to the button
The ContactsList activity
This activity extends the ListActivity class. It has its own default layout so we don’t have to include one.
We use it to display a list of contact’s names.
This ListActivity displays a scrollable list of names
Check out this tutorial for more on lists, Android ListView tutorial.
Basically there are two parts to this activity:
- In the activity’s onCreate() method we create an adapter and attach it to the list view to supply the contact names from the contactsList array
- The onListItemClick() method which is triggered when a list item is selected. Here we use an intent containing the selected item’s list position to start the DisplayContact activity
Here’s how we convert this activity to the fragment equivalent, the ContactsListFragment fragment.
ContactsListFragment fragment
This fragment extends the ListFragment class, the fragment equivalent of the ListActivity class.
- We move the adapter code from the activity’s onCreate() method to the fragment’s onActivityCreated() method. This method is called after the fragment’s onCreateView() method, once the MainActivity activity has been created
- This list fragment also has an onListItemClick()method which is triggered when a list item is selected. We use our custom listener interface, OnContactSelectedListener’s callback to execute the onContactSelected() method in the MainActivity (see the discussion of this above where we discuss the MainActivity). In it we create and display the DisplayContactFragment fragment, displaying the selected contact’s image (well actually a placeholder image) and their name
- We also have the required empty fragment constructor
- Then there’s our custom listener interface
Here’s the code for the listener interface:
We need an interface to send the selected item’s position to the MainActivity activity
So what’s this?
This is our custom callback interface which we use to send the selected item’s position back to the MainActivity.
Each time the user selects an item, the onListItemClick()method is triggered, which in turn calls the onContactSelected() method, passing on the selected item’s position.
- Finally, we include the fragment’s onAttach() method
Here’s the code for the onAttach() method:
Make sure that the MainActivity implements the callback interface
So what’s this?
This method is called when the fragment is first attached to the MainActivity activity. We use it to check that the activity implements our interface else it throws an error.
The DisplayContact activity
This activity displays the selected contact’s name and image.
We display the selected contact’s name and image
Here’s the code that does the work. It’s all in the activity’s onCreate() method:
Get the selected item’s position and then display the matching name and image
So what’s this?
First we get a reference to the TextView that we’ll use to display the contact’s name.
Next we get the selected contact’s position in the list which was passed here from the ContactsList activity in the intent. Then we use an if else statement to check that we have a valid value for position.
- If it’s valid then we use the position value as an index to the contactsList array to get the selected contact’s name. The name is then displayed. The default image will also be displayed
- If position is not valid (it’s -1) then display the problem drawable in the ImageView along with an appropriate text message
Here’s how we convert the activity to the fragment equivalent, the DisplayContactFragment fragment.
DisplayContactFragment fragment
This fragment displays the selected contact’s name and image.
The fragment has two methods:
- The required empty constructor
- The onCreateView() method. This method inflates the fragment’s layout providing the User Interface. We then include the same code that is contained in the activity’s onCreate() method
The XML layouts
The layouts determine how the views are laid out on the screen.
In the fragment version of the app, the main activity has a container layout. All the fragments are then displayed in this container (one at a time as the user navigates through the app).
All the fragment’s layouts are standard layouts, exactly the same as you would use for any activity.
The MainActivity activity’s layout
The main activity displays the various fragments in a FrameLayout container.
Here’s the XML code:
The MainActivity activity’s fragment container
So what’s this?
It’s a normal LinearLayout containing a FrameLayout.
- The FrameLayout acts as a container in which we swop the various fragments. It has a unique ID which we use when we add a fragment to or replace a fragment in the container:
Fragments are added to or replaced in the fragment_container
So what’s this?
Note the FrameLayout’s ID, R.id.fragment_container in the calls to add or replace a fragment.
The remaining fragments XML layouts
The remaining fragments have normal layouts just like those that you would use for activities.
The landscape version
We include both a default portrait version and a landscape version of the DisplayContactFragment fragment’s layout. Both are named fragment_display_contact.xml.
The landscape version is used if the device is in landscape mode:
The system chooses the correct layout at runtime
I hope that you have found this tutorial helpful.
This project was created using .
You can download the project files here
.