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