This tutorial is about developing a
TabLayout / tabs which is one of the
very important ways of providing the UI in Android. The default Contacts application uses this
layout.
For creating a tab Layout, we need to look
at 3 new aspects: TabActivity,
TabHost
and TabWidget.
Let us begin by looking at how we should
declare the layout xml. The root node
has to be a TabHost.
What is a TabHost
and why is it required? It is nothing but a container for the tabbed view we
want to create. It provides methods to add the tabs, remove them and to bring
focus to a specific tab etc.
Within this, we need to have a two objects:
TabWidget
and a FrameLayout.
The TabWidget
itself does not do much except contain a list of tab labels that exist within
the parent TabHost.
Basically it is nothing but a set of
labels that the user clicks in order to select a specific tab. The actual
content of each tab is to be held by the 2nd object in the TabHost
i.e. a FrameLayout.
Hence both the TabWidget
and FrameLayout
need to be present on each tab. And in order to align htme one after another,
we embed them into a LinearLayout.
Hence the layout XML would be like this:
<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:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"></TabWidget>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"></FrameLayout>
</LinearLayout>
</TabHost>
Now, we will move on to the coding of
activities for a Tabbed Layout.
In the application, I want to have 3 tabs.
So how do I do it?
Each of the tabs can have either a View,
launch an activity by passing an intent or create a view dynamically by using TabHost.TabContentFactory.
I have chosen to show only activities in all my tabs.
So, how many activities do you think we
need? 3? Sorry 4! There needs to be a main or the parent activity that would
display the whole tabbed view and one activity in each of the tabs.
Now let us look at developing the main
activity. This has to extend the TabActivity.
This is no different from an Activity
except for the additional ability to handle multiple embedded activities or
views.
So here is the main class declaration:
public class TabLayoutSample extends TabActivity {
Let us see now, how to create the first
tab.
First, we need to get a handle to the TabHost
that we have declared in the XML layout file, so that we can add tab activities
into it. Here is the code for the same:
TabHost tabHost = getTabHost(); // The activity TabHost
Into this TabHost,
we need to add the tab. How can we? TabHost
provides an inner class called TabSpec
that allows you to create a tab, populate its contents and add it as a tab to
the TabHost. See how it is done:
TabHost.TabSpec spec;
// Create an Intent to launch an Activity for the tab (to be reused)
intent = new Intent().setClass(this, WelcomeActivity.class);
// Initialize
a TabSpec for each tab and add it to the TabHost
spec = tabHost.newTabSpec("welcome").setIndicator("Welcome",
res.getDrawable(R.drawable.tab_welcome))
.setContent(intent);
tabHost.addTab(spec);
In the first line above, we are creating a
spec variable of type TabSpec.
Then we are creating an intent that would be forming the content of the first
tab. Then, we associate it with the TabSpec.
Since, each tab should have a tab
indicator, content and a tag to keep track of it, it is achieved through setIndicator(..) method. Even the
image that should be shown in the tab at the top is set through the same method’s
2nd parameter res.getDrawable(R.Drawable.tab_welcome). What is this and how did I set the image?
This part is a long set of steps but very
easy to do. Create two images one in light color and one in dark color. Call
them as welcome.png and welcome_sepia.png. Copy them into the /res/drawable-mdpi folder. The, you need to create a state-list drawable that specifies which image to use for each tab state:
[A StateListDrawable is
a drawable object defined in XML that uses a several different images to represent
the same graphic, depending on the state of the object. For example, a Button
widget can exist in one of several different states (pressed, focused, or neither)
and, using a state list drawable, you can provide a different background image
for each state.]
So, here is the tab_welcome.xml:
<?xml version="1.0"
encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- When
selected, use grey -->
<item android:drawable="@drawable/welcome"
android:state_selected="true"
/>
<!-- When
not selected, use white-->
<item android:drawable="@drawable/welcome_sepia"
/>
</selector>
This XML is describing
which welcome image to show when the tab is selected and which to show when the
tab is not selected. This XML too needs
to be created in the same folder - /res/drawable-mdpi.
Once all of this is done, when setIndicator("Welcome",
res.getDrawable(R.drawable.tab_welcome))is called, the image
associated with the tab is shown correctly based on the state.
Then,
the last part of the tabSpec call is associating the activity that should be
shown in the content of the activity. For this, I have created a new Intent which invokes an Activity
– ‘WelcomeActivity.class’. this
implies that the WelcomeActivity.class is already
created and available. In this case, it just contains a welcome message to be
shown.
I have repeated the above to show existing
“contacts” in the next tab and then the “top links” in the third tab. You can
get the
complete code for the same here.