page.title=Tab Layout parent.title=Hello, Views parent.link=index.html @jd:body
To create a tabbed UI, you need to use a {@link android.widget.TabHost} and a {@link android.widget.TabWidget}. The {@link android.widget.TabHost} must be the root node for the layout, which contains both the {@link android.widget.TabWidget} for displaying the tabs and a {@link android.widget.FrameLayout} for displaying the tab content.
You can implement your tab content in one of two ways: use the tabs to swap {@link android.view.View}s within the same {@link android.app.Activity}, or use the tabs to change between entirely separate activities. Which method you want for your application will depend on your demands, but if each tab provides a distinct user activity, then it probably makes sense to use a separate {@link android.app.Activity} for each tab, so that you can better manage the application in discrete groups, rather than one massive application and layout.
In this tutorial, you'll create a tabbed UI that uses a separate {@link android.app.Activity} for each tab.
ArtistsActivity, AlbumsActivity, and SongsActivity. These
will each represent a separate tab. For now, make each one display a simple message using a {@link
android.widget.TextView}. For example:
public class ArtistsActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textview = new TextView(this);
textview.setText("This is the Artists tab");
setContentView(textview);
}
}
Notice that this doesn't use a layout file. Just create a {@link
android.widget.TextView}, give it some text and set that as the content. Duplicate this for
each of the three activities, and add the corresponding <activity/> tags to the Android Manifest file.
Copy these images for use in this tutorial. Save them into your project
res/drawable/ directory. You now need to create a {@link
android.graphics.drawable.Drawable} with XML that specifies which image
to use for each state. Create a new file in res/drawable/ named
ic_tab_artists.xml and insert the following:
<?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/ic_tab_artists_grey"
android:state_selected="true" />
<!-- When not selected, use white-->
<item android:drawable="@drawable/ic_tab_artists_white" />
</selector>
This is an XML definition for a {@link android.graphics.drawable.Drawable}, which you will reference as the image for a tab. When the image state changes, the image will automatically switch between the images defined here.
res/layout/main.xml file and insert the following:
<?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"
android:padding="5dp">
<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"
android:padding="5dp" />
</LinearLayout>
</TabHost>
This is the layout that will display the tabs and provide navigation between each {@link android.app.Activity} created above.
The {@link android.widget.TabHost} requires that a {@link android.widget.TabWidget} and a {@link android.widget.FrameLayout} both live somewhere within it. To position the {@link android.widget.TabWidget} and {@link android.widget.FrameLayout} vertically, a {@link android.widget.LinearLayout} is used. The {@link android.widget.FrameLayout} is where the content for each tab goes, which is empty now because the {@link android.widget.TabHost} will automatically embed each {@link android.app.Activity} within it.
Notice that the {@link android.widget.TabWidget} and the {@link android.widget.FrameLayout} elements have the IDs {@code tabs} and {@code tabcontent}, respectively. These names must be used so that the {@link android.widget.TabHost} can retrieve references to each of them. It expects exactly these names.
HelloTabWidget.java and make it extend {@link
android.app.TabActivity}:
public class HelloTabWidget extends TabActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Resources res = getResources(); // Resource object to get Drawables
TabHost tabHost = getTabHost(); // The activity TabHost
TabHost.TabSpec spec; // Resusable TabSpec for each tab
Intent intent; // Reusable Intent for each tab
// Create an Intent to launch an Activity for the tab (to be reused)
intent = new Intent().setClass(this, ArtistsActivity.class);
// Initialize a TabSpec for each tab and add it to the TabHost
spec = tabHost.newTabSpec("artists").setIndicator("Artists",
res.getDrawable(R.drawable.ic_tab_artists))
.setContent(intent);
tabHost.addTab(spec);
// Do the same for the other tabs
intent = new Intent().setClass(this, AlbumsActivity.class);
spec = tabHost.newTabSpec("albums").setIndicator("Albums",
res.getDrawable(R.drawable.ic_tab_albums))
.setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, SongsActivity.class);
spec = tabHost.newTabSpec("songs").setIndicator("Songs",
res.getDrawable(R.drawable.ic_tab_songs))
.setContent(intent);
tabHost.addTab(spec);
tabHost.setCurrentTab(2);
}
This sets up each tab with their text and icon, and assigns each one an {@link android.app.Activity}.
A reference to the {@link android.widget.TabHost} is first captured with {@link android.app.TabActivity#getTabHost()}. Then, for each tab, a {@link android.widget.TabHost.TabSpec} is created to define the tab properties. The {@link android.widget.TabHost#newTabSpec(String)} method creates a new {@link android.widget.TabHost.TabSpec} identified by the given string tag. For each {@link android.widget.TabHost.TabSpec}, {@link android.widget.TabHost.TabSpec#setIndicator(CharSequence,Drawable)} is called to set the text and icon for the tab, and {@link android.widget.TabHost.TabSpec#setContent(Intent)} is called to specify the {@link android.content.Intent} to open the appropriate {@link android.app.Activity}. Each {@link android.widget.TabHost.TabSpec} is then added to the {@link android.widget.TabHost} by calling {@link android.widget.TabHost#addTab(TabHost.TabSpec)}.
At the very end, {@link android.widget.TabHost#setCurrentTab(int)} opens the tab to be displayed by default, specified by the index position of the tab.
Notice that not once was the {@link android.widget.TabWidget} object referenced. This is because a {@link android.widget.TabWidget} must always be a child of a {@link android.widget.TabHost}, which is what you use for almost all interaction with the tabs. So when a tab is added to the {@link android.widget.TabHost}, it's automatically added to the child {@link android.widget.TabWidget}.
NoTitleBar theme to the
HelloTabWidget's
<activity> tag. This will remove the default application title from the top
of the layout, leaving more space for the tabs, which effectively operate as their own titles.
The <activity> tag should look like this:
<activity android:name=".HelloTabWidget" android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar">
Your application should look like this: