Widget Catalog: TabHost and TabWidget

Before we had the action bar and ViewPager, we had TabHost and TabWidget as our means of displaying tabs. Nowadays, in most cases, using tabs with a ViewPager is the preferred option. However, there may be cases where the classic tabs are a better solution, or you may have inherited legacy code that still uses TabHost.

Deprecation Notes

Just as ListActivity helps one use a ListView, TabActivity helps one use a TabHost. However, TabActivity is marked as deprecated. That is largely because its parent class, ActivityGroup, is deprecated. While you can still use TabActivity, it is no longer recommended. It also is not necessary, as there are ways to use TabHost and TabWidget without using TabActivity, as will be demonstrated later in this chapter.

Key Usage Tips

There are a few widgets and containers you need to use in order to set up a tabbed portion of a view:

You load contents into that FrameLayout in one of two ways:

  1. You can define the contents simply as child widgets (or containers) of the FrameLayout in a layout XML file you are using for the whole tab setup
  2. You can define the contents at runtime

Curiously, you do not define what goes in the tabs themselves, or how they tie to the content, in the layout XML file. Instead, you must do that in Java, by creating a series of TabSpec objects (obtained via newTabSpec() on TabHost), configuring them, then adding them in sequence to the TabHost via addTab().

The two key methods on TabSpec are:

Note that tab “indicators” can actually be views in their own right, if you need more control than a simple label and optional icon.

Also note that you must call setup() on the TabHost before configuring any of these TabSpec objects. The call to setup() is not needed if you are using the TabActivity base class for your activity.

A Sample Usage

The sample project can be found in WidgetCatalog/Tab.

Layout:

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/tabhost"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TabWidget android:id="@android:id/tabs"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
    />
    <FrameLayout android:id="@android:id/tabcontent"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
      <AnalogClock android:id="@+id/tab1"
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
      />
      <Button android:id="@+id/tab2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="A semi-random button"
      />
    </FrameLayout>
  </LinearLayout>
</TabHost>
(from WidgetCatalog/Tab/app/src/main/res/layout/main.xml)

Activity:

package com.commonsware.android.tabhost;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TabHost;

public class TabDemo extends Activity {
  @Override
  public void onCreate(Bundle state) {
    super.onCreate(state);
    setContentView(R.layout.main);

    TabHost tabs=(TabHost)findViewById(R.id.tabhost);

    tabs.setup();

    TabHost.TabSpec spec=tabs.newTabSpec("tag1");

    spec.setContent(R.id.tab1);
    spec.setIndicator("Clock");
    tabs.addTab(spec);

    spec=tabs.newTabSpec("tag2");
    spec.setContent(R.id.tab2);
    spec.setIndicator("Button");
    tabs.addTab(spec);
  }
}
(from WidgetCatalog/Tab/app/src/main/java/com/commonsware/android/tabhost/TabDemo.java)

Note that ordinarily you would use icons with your tabs, and so the second parameter to setIndicator() would be a reference to a drawable resource. This particular sample skips the icons.

Visual Representation

This is what a TabHost and TabWidget look like in a few different Android versions and configurations, based upon the sample app shown above.

Android 2.3.3
Figure 1054: Android 2.3.3

Android 4.0.3
Figure 1055: Android 4.0.3