Home | History | Annotate | Download | only in views
      1 page.title=Tab Layout
      2 parent.title=Hello, Views
      3 parent.link=index.html
      4 @jd:body
      5 
      6 <p>To create a tabbed UI, you need to use a {@link android.widget.TabHost} and a {@link
      7 android.widget.TabWidget}. The {@link android.widget.TabHost} must be the root node for the layout,
      8 which contains both the {@link android.widget.TabWidget} for displaying the tabs and a {@link
      9 android.widget.FrameLayout} for displaying the tab content.</p>
     10 
     11 <p>You can implement your tab content in one of two ways: use the tabs to swap
     12 {@link android.view.View}s within the same {@link android.app.Activity}, or use the tabs to change
     13 between entirely separate activities. Which method you want for your application will depend on your
     14 demands, but if each tab provides a distinct user activity, then it probably makes sense to use
     15 a separate {@link android.app.Activity} for each tab, so that you can better manage the application
     16 in discrete groups, rather than one massive application and layout.</p>
     17 
     18 <p>In this tutorial, you'll create a tabbed UI that uses a separate {@link
     19 android.app.Activity} for each tab.</p>
     20 
     21 <ol>
     22   <li>Start a new project named <em>HelloTabWidget</em>.</li>
     23   <li>First, create three separate {@link android.app.Activity} classes in your project:
     24 <code>ArtistsActivity</code>, <code>AlbumsActivity</code>, and <code>SongsActivity</code>. These
     25 will each represent a separate tab. For now, make each one display a simple message using a {@link
     26 android.widget.TextView}. For example:
     27 <pre>
     28 public class ArtistsActivity extends Activity {
     29     public void onCreate(Bundle savedInstanceState) {
     30         super.onCreate(savedInstanceState);
     31 
     32         TextView textview = new TextView(this);
     33         textview.setText("This is the Artists tab");
     34         setContentView(textview);
     35     }
     36 }
     37 </pre>
     38   <p>Notice that this doesn't use a layout file. Just create a {@link
     39 android.widget.TextView}, give it some text and set that as the content. Duplicate this for
     40 each of the three activities, and add the corresponding <code>&lt;activity/&gt;</code> tags to the Android Manifest file.</p>
     41 
     42   <li>You need an icon for each of your tabs. For each icon, you should create two versions: one
     43 for when the tab is selected and one for when it is unselected. The
     44 general design recommendation is for the selected icon to be a dark color (grey), and the
     45 unselected icon to be a light color (white). (See the <a
     46 href="{@docRoot}guide/practices/ui_guidelines/icon_design.html#tabstructure">Icon Design
     47 Guidelines</a>.) For example:
     48   <p>
     49   <img src="images/ic_tab_artists_white.png" title="unselected tab icon"  alt="" />
     50   <img src="images/ic_tab_artists_grey.png" title="selected tab icon" alt="" />
     51   </p>
     52   <p>For this tutorial, you can copy these images and use them for all three tabs. (When you
     53 create tabs in your own application, you should create customized tab icons.)</p>
     54   <p>Now create a <a
     55 href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">state-list drawable</a>
     56 that specifies which image to use for each tab state:</p>
     57   <ol>
     58     <li>Save the icon images in your project <code>res/drawable/</code> directory.</li>
     59     <li>Create a new XML file in <code>res/drawable/</code>
     60 named <code>ic_tab_artists.xml</code> and insert the following:
     61 <pre>
     62 &lt;?xml version="1.0" encoding="utf-8"?>
     63 &lt;selector xmlns:android="http://schemas.android.com/apk/res/android">
     64     &lt;!-- When selected, use grey -->
     65     &lt;item android:drawable="@drawable/ic_tab_artists_grey"
     66           android:state_selected="true" />
     67     &lt;!-- When not selected, use white-->
     68     &lt;item android:drawable="@drawable/ic_tab_artists_white" />
     69 &lt;/selector>
     70 </pre>
     71   <p>This is a <a
     72 href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">state-list drawable</a>,
     73 which you will apply as the tab image. When the tab state changes, the tab icon will
     74 automatically switch between the images defined here.</p>
     75     </li>
     76   </ol>
     77   </li>
     78 
     79   <li>Open the <code>res/layout/main.xml</code> file and insert the following:
     80   <pre>
     81 &lt;?xml version="1.0" encoding="utf-8"?>
     82 &lt;TabHost xmlns:android="http://schemas.android.com/apk/res/android"
     83     android:id="@android:id/tabhost"
     84     android:layout_width="fill_parent"
     85     android:layout_height="fill_parent">
     86     &lt;LinearLayout
     87         android:orientation="vertical"
     88         android:layout_width="fill_parent"
     89         android:layout_height="fill_parent"
     90         android:padding="5dp">
     91         &lt;TabWidget
     92             android:id="@android:id/tabs"
     93             android:layout_width="fill_parent"
     94             android:layout_height="wrap_content" />
     95         &lt;FrameLayout
     96             android:id="@android:id/tabcontent"
     97             android:layout_width="fill_parent"
     98             android:layout_height="fill_parent"
     99             android:padding="5dp" />
    100     &lt;/LinearLayout>
    101 &lt;/TabHost>
    102 </pre>
    103     <p>This is the layout that will display the tabs and provide navigation between each {@link
    104     android.app.Activity} created above.</p>
    105     <p>The {@link android.widget.TabHost} requires that a {@link android.widget.TabWidget} and a
    106 {@link android.widget.FrameLayout} both live somewhere within it. To position the {@link
    107 android.widget.TabWidget} and {@link android.widget.FrameLayout} vertically, a {@link
    108 android.widget.LinearLayout} is used. The {@link android.widget.FrameLayout} is where the content
    109 for each tab goes, which is empty now because the {@link android.widget.TabHost} will automatically
    110 embed each {@link android.app.Activity} within it.</p>
    111     <p>Notice that the {@link android.widget.TabWidget} and the {@link android.widget.FrameLayout}
    112     elements have the IDs {@code tabs} and {@code tabcontent}, respectively. These names
    113     must be used so that the {@link android.widget.TabHost} can retrieve references to each of
    114     them. It expects exactly these names.</p>
    115   </li>
    116 
    117   <li>Now open <code>HelloTabWidget.java</code> and make it extend {@link
    118   android.app.TabActivity}:</p>
    119 <pre>
    120 public class HelloTabWidget extends TabActivity {
    121 </pre>
    122   </li>
    123   <li>Use the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()}
    124   method:
    125 <pre>
    126 public void onCreate(Bundle savedInstanceState) {
    127     super.onCreate(savedInstanceState);
    128     setContentView(R.layout.main);
    129 
    130     Resources res = getResources(); // Resource object to get Drawables
    131     TabHost tabHost = getTabHost();  // The activity TabHost
    132     TabHost.TabSpec spec;  // Resusable TabSpec for each tab
    133     Intent intent;  // Reusable Intent for each tab
    134 
    135     // Create an Intent to launch an Activity for the tab (to be reused)
    136     intent = new Intent().setClass(this, ArtistsActivity.class);
    137 
    138     // Initialize a TabSpec for each tab and add it to the TabHost
    139     spec = tabHost.newTabSpec("artists").setIndicator("Artists",
    140                       res.getDrawable(R.drawable.ic_tab_artists))
    141                   .setContent(intent);
    142     tabHost.addTab(spec);
    143 
    144     // Do the same for the other tabs
    145     intent = new Intent().setClass(this, AlbumsActivity.class);
    146     spec = tabHost.newTabSpec("albums").setIndicator("Albums",
    147                       res.getDrawable(R.drawable.ic_tab_albums))
    148                   .setContent(intent);
    149     tabHost.addTab(spec);
    150 
    151     intent = new Intent().setClass(this, SongsActivity.class);
    152     spec = tabHost.newTabSpec("songs").setIndicator("Songs",
    153                       res.getDrawable(R.drawable.ic_tab_songs))
    154                   .setContent(intent);
    155     tabHost.addTab(spec);
    156 
    157     tabHost.setCurrentTab(2);
    158 }
    159 </pre>
    160     <p>This sets up each tab with their text and icon, and assigns each one an {@link
    161 android.app.Activity}.</p>
    162     <p>A reference to the {@link android.widget.TabHost} is first captured with {@link
    163 android.app.TabActivity#getTabHost()}. Then, for
    164 each tab, a {@link android.widget.TabHost.TabSpec} is created to define the tab properties. The
    165 {@link android.widget.TabHost#newTabSpec(String)} method creates a new {@link
    166 android.widget.TabHost.TabSpec} identified by the given string tag. For each
    167 {@link android.widget.TabHost.TabSpec}, {@link
    168 android.widget.TabHost.TabSpec#setIndicator(CharSequence,Drawable)} is called to set the text and
    169 icon for the tab, and {@link android.widget.TabHost.TabSpec#setContent(Intent)} is called to specify
    170 the {@link android.content.Intent} to open the appropriate {@link android.app.Activity}. Each
    171 {@link android.widget.TabHost.TabSpec} is then added to the {@link android.widget.TabHost} by
    172 calling {@link android.widget.TabHost#addTab(TabHost.TabSpec)}.</p>
    173 
    174     <p>At the very end, {@link
    175     android.widget.TabHost#setCurrentTab(int)} opens the tab to be displayed by default, specified
    176     by the index position of the tab.</p>
    177 
    178     <p>Notice that not once was the {@link android.widget.TabWidget} object referenced. This is
    179     because a {@link android.widget.TabWidget} must always be a child of a {@link
    180     android.widget.TabHost}, which is what you use for almost all interaction with the tabs. So when
    181     a tab is added to the {@link android.widget.TabHost}, it's automatically added to the child
    182     {@link android.widget.TabWidget}.</p>
    183   </li>
    184 
    185   <li>Now open the Android Manifest file and add the <code>NoTitleBar</code> theme to the
    186 <em>HelloTabWidget</em>'s
    187   <code>&lt;activity></code> tag. This will remove the default application title from the top
    188   of the layout, leaving more space for the tabs, which effectively operate as their own titles.
    189   The <code>&lt;activity></code> tag should look like this:
    190 <pre>
    191 &lt;activity android:name=".HelloTabWidget" android:label="@string/app_name"
    192           android:theme="&#64;android:style/Theme.NoTitleBar">
    193 </pre>
    194   </li>
    195 
    196   <li>Run the application.</li>
    197 </ol>
    198 
    199 
    200 <p>Your application should look like this (though your icons may be different):</p>
    201 <img src="images/hello-tabwidget.png" width="150px" />
    202 
    203 <h3>References</h3>
    204 <ul>
    205 <li>{@link android.widget.TabWidget}</li>
    206 <li>{@link android.widget.TabHost}</li>
    207 <li>{@link android.widget.TabHost.TabSpec}</li>
    208 <li>{@link android.widget.FrameLayout}</li>
    209 </ul>
    210 
    211