diff options
Diffstat (limited to 'docs/html/resources/tutorials/views/hello-tabwidget.jd')
-rw-r--r-- | docs/html/resources/tutorials/views/hello-tabwidget.jd | 220 |
1 files changed, 148 insertions, 72 deletions
diff --git a/docs/html/resources/tutorials/views/hello-tabwidget.jd b/docs/html/resources/tutorials/views/hello-tabwidget.jd index 8424616..199ceef 100644 --- a/docs/html/resources/tutorials/views/hello-tabwidget.jd +++ b/docs/html/resources/tutorials/views/hello-tabwidget.jd @@ -1,14 +1,72 @@ -page.title=Hello, TabWidget +page.title=Tab Layout parent.title=Hello, Views parent.link=index.html @jd:body -<p>A {@link android.widget.TabWidget} offers the ability to easily draw an interface that uses -tabs to navigate between different views.</p> +<p>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.</p> + +<p>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.</p> + +<p>In this tutorial, you'll create a tabbed UI that uses a separate {@link +android.app.Activity} for each tab.</p> <ol> - <li>Start a new project/Activity called HelloTabWidget.</li> - <li>Open the layout file and make it like so:</li> + <li>Start a new project named <em>HelloTabWidget</em>.</li> + <li>First, create three separate {@link android.app.Activity} classes in your project: +<code>ArtistsActivity</code>, <code>AlbumsActivity</code>, and <code>SongsActivity</code>. These +will each represent a separate tab. For now, make each one display a simple message using a {@link +android.widget.TextView}. For example: +<pre> +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); + } +} +</pre> + <p>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.</p> + + <li>You're going to need an icon for each of your tabs. And for each one, you should create an +image for two different states: one for when the tab is selected, and one for when it is not. The +general design recommendation is for the selected tab icon to be a darker color (grey), and the +non-selected icon to be lighter (white). For example: + <p> + <img src="images/ic_tab_artists_white.png" title="ic_tab_artists_white.png" alt="" /> + <img src="images/ic_tab_artists_grey.png" title="ic_tab_artists_grey.png" alt="" /> + </p> + <p>Copy these images for use in this tutorial. Save them into your project +<code>res/drawable/</code> 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 <code>res/drawable/</code> named +<code>ic_tab_artists.xml</code> and insert the following:</p> +<pre> +<?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> +</pre> + <p>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.</p> + + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" @@ -18,7 +76,8 @@ tabs to navigate between different views.</p> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" - android:layout_height="fill_parent"> + android:layout_height="fill_parent" + android:padding="5dp"> <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" @@ -26,94 +85,111 @@ tabs to navigate between different views.</p> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" - android:layout_height="fill_parent"> - <TextView - android:id="@+id/textview1" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:text="this is a tab" /> - <TextView - android:id="@+id/textview2" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:text="this is another tab" /> - <TextView - android:id="@+id/textview3" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:text="this is a third tab" /> - </FrameLayout> + android:layout_height="fill_parent" + android;padding="5dp" /> </LinearLayout> </TabHost> </pre> - <p>Here, we've created a {@link android.widget.TabHost} that contains the entire layout of the Activity. - A TabHost requires two descendant elements: a {@link android.widget.TabWidget} and a {@link android.widget.FrameLayout}. - In order to properly layout these elements, we've put them inside a vertical {@link android.widget.LinearLayout}. - The FrameLayout is where we keep the content that will change with each tab. Each child in the FrameLayout will - be associated with a different tab. - In this case, each tab simply shows a different {@link android.widget.TextView} with some text. </p> - <p>Notice that the TabWidget and the FrameLayout elements have specific <code>android</code> namespace IDs. These are necessary - so that the TabHost can automatically retireve references to them, populate the TabWidget with the tabs that we'll define - in our code, and swap the views in the FrameLayout. We've also defined our own IDs for each TextView, which we'll use to - associate each tab with the view that it should reveal.</p> - <p>Of course, you can - make these child views as large as complex as you'd like — instead of the TextView elements, - you could start with other layout views and build a unique layout hierarchy for each tab.</p> + <p>This is the layout that will display the tabs and provide navigation between each {@link + android.app.Activity} created above.</p> + <p>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.</p> + <p>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.</p> </li> - <li>Now we'll add our code. Open HelloTabWidget.java and make it a <code>TabActivity</code>. - <p>By default, Eclipse creates a class that extends <code>Activity</code>. Change it to - extend <code>TabActivity</code>:</p> - <pre> + + <li>Now open <code>HelloTabWidget.java</code> and make it extend {@link + android.app.TabActivity}:</p> +<pre> public class HelloTabWidget extends TabActivity { -</pre> +</pre> </li> - <li>Now fill in the the <code>onCreate</code> method like this: - <pre> + <li>Use the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} + method: +<pre> public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); - mTabHost = getTabHost(); - - mTabHost.addTab(mTabHost.newTabSpec("tab_test1").setIndicator("TAB 1").setContent(R.id.textview1)); - mTabHost.addTab(mTabHost.newTabSpec("tab_test2").setIndicator("TAB 2").setContent(R.id.textview2)); - mTabHost.addTab(mTabHost.newTabSpec("tab_test3").setIndicator("TAB 3").setContent(R.id.textview3)); - - mTabHost.setCurrentTab(0); + 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); + mTabHost.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(getIntent()); } </pre> - <p>As usual, we start by setting our layout.</p> - <p>We then call the TabActivity method <code>getTabHost()</code>, - which returns us a reference to the TabHost we created in our layout. Upon our TabHost, we call <code>addTab()</code> - for each of the tabs that we want to add to the TabWidget. Each time we call this, we pass a - {@link android.widget.TabHost.TabSpec} that we build on the fly, and with it, chain together two necessary methods: - <code>setIndicator()</code> to set the text for the tab button, and <code>setContent()</code> to define - which View we want to associate with the tab and reveal when pressed. Our indicator is just a text string and - our content is an ID reference to the TextView elements we inserted in the FrameLayout.</p> - <p>At the end, we call <code>setCurrentTab()</code> to define which tab should be opened by default. The tabs - are saved like a zero-based array, so to open the first tab, we pass zero (<var>0</var>).</p> + <p>This sets up each tab with their text and icon, and assigns each one an {@link +android.app.Activity}.</p> + <p>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 opens 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)}.</p> + + <p>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.</p> + + <p>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}.</p> </li> - <li>To clean-up the presentation a bit more, let's remove the window title that appears at the top of the layout. - Android includes a theme that removes that title for us. To add it, open the Android Manifest file and add - the <var>NoTitleBar</var> theme to the <code><application></code> tag. It should end up like this: - <pre> -<application android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar"> + + <li>Now open the Android Manifest file and add the <code>NoTitleBar</code> theme to the +<em>HelloTabWidget</em>'s + <code><activity></code> 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 <code><activity></code> tag should look like this: +<pre> +<activity android:name=".HelloTabWidget" android:label="@string/app_name" + android:theme="@android:style/Theme.NoTitleBar"> </pre> </li> - <li>That's it. Run your application.</li> + <li>Run the application.</li> </ol> <p>Your application should look like this:</p> <img src="images/hello-tabwidget.png" width="150px" /> -<div class="special"><p>You can include icons in your tabs by passing a -{@link android.graphics.drawable.Drawable} when you call <code>setIndicator()</code>. Here's an example -that uses a Drawable created from an image in the project resources:</p> -<pre>setIndicator("TAB 1", getResources().getDrawable(R.drawable.tab_icon))</pre> -</div> - <h3>References</h3> <ul> <li>{@link android.widget.TabWidget}</li> |