Wiring It Together

The Java code needs to tell the TabHost what views represent the tab contents and what the tab buttons should look like. This is all wrapped up in TabSpec objects. You get a TabSpec instance from the host via newTabSpec(), fill it out, then add it to the host in the proper sequence. The two key methods on TabSpec are:

• setContent(), where you indicate what goes in the tab content for this tab, typically the android:id of the view you want shown when this tab is selected

• setIndicator(), where you provide the caption for the tab button and, in some flavors of this method, supply a Drawable to represent the icon for the tab

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.

For example, here is the Java code to wire together the tabs from the preceding layout example:

package com.commonsware.android.fancy;

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

public class TabDemo extends Activity { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); 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);

tabs.setCurrentTab(0);

We find our TabHost via the familiar findViewById() method, then have it call setup(). After that, we get a TabSpec via newTabSpec(), supplying a tag whose purpose is unknown at this time. Given the spec, you call setContent() and setIndicator(), then call addTab() back on the TabHost to register the tab as available for use. Finally, you can choose which tab is the one to show via setCurrentTab(), providing the 0-based index of the tab. The results can be seen in Figures 10-5 and 10-6.

Figure 10-5. The TabDemo sample application, showing the first tab
Figure 10-6. The same application, showing the second tab

Adding Them Up

TabWidget is set up to allow you to easily define tabs at compile time. However, sometimes, you want to add tabs to your activity during runtime. For example, imagine an email client where individual emails get opened in their own tab for easy toggling between messages. In this case, you don't know how many tabs or what their contents will be until runtime, when the user chooses to open a message.

Fortunately, Android also supports adding tabs dynamically at runtime. Adding tabs dynamically at runtime works much like the compile-time tabs previously shown, except you use a different flavor of setContent(), one that takes a TabHost. TabContentFactory instance. This is just a callback that will be invoked—you provide an implementation of createTabContent() and use it to build and return the Let's take a look at an example (Fancy/DynamicTab).

First, here is some layout XML for an activity that sets up the tabs and defines one tab, containing a single button:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout width="fill parent" android:layout height="fill parent">

<TabHost android:id="@+id/tabhost" android:layout width="fill parent" android:layout height="fill parent"> <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:paddingTop="62px"> <Button android:id="@+id/buttontab" android:layout width="fill parent" android:layout height="fill parent" android:text="A semi-random button"

</FrameLayout> </TabHost> </LinearLayout>

What we want to do is add new tabs whenever the button is clicked. That can be accomplished in just a few lines of code:

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

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

TabHost.TabSpec spec=tabs.newTabSpec("buttontab"); spec.setContent(R.id.buttontab); spec.setIndicator("Button"); tabs.addTab(spec);

tabs.setCurrentTab(0);

Button btn=(Button)tabs.getCurrentView().findViewById(R.id.buttontab);

btn.setOnClickListener(new View.OnClickListener() {

public void onClick(View view) { TabHost.TabSpec spec=tabs.newTabSpec("tag1");

spec.setContent(new TabHost.TabContentFactory() { public View createTabContent(String tag) { return(new AnalogClock(DynamicTabDemo.this));

spec.setIndicator("Clock"); tabs.addTab(spec);

In our button's setOnClickListener() callback, we create a TabHost.TabSpec object and give it an anonymous TabHost.TabContentFactory. The factory, in turn, returns the View to be used for the tab—in this case, just an AnalogClock. The logic for constructing the tab's View could be much more elaborate, such as using LayoutInflater to construct a view from layout XML.

In Figure 10-7 you can see that initially, when the activity is launched, we just have the one tab whereas Figure 10-8 shows multiple tabs.

Figure 10-7. The DynamicTab application, with the single initial tab

A semi-random button

Figure 10-8. The DynamicTab application, with three dynamically-created tabs

Intents and Views

In the preceding examples, the contents of each tab were set to be a View, such as a Button. This is easy and straight-forward, but it is not the only option. You can also integrate another activity from your application via an Intent.

Intents are ways of specifying something you want accomplished, then telling Android to go find something to accomplish it. Frequently, these are used to cause activities to spawn. For example, whenever you launch an application from the main Android application launcher, the launcher creates an Intent and has Android open up the activity associated with that Intent. This whole concept, and how activities can be placed in tabs, will be described in greater detail in Chapter 25.

0 0

Post a comment