Android控件篇21之 TabHost

本文介绍TabHost。

1. TabHost简介

TabHost与Tab的关系,就好比AppWidget和AppWidgetHost。TabHost可以包含Tab。在使用TabHost时,通常都会用到TabActivity。TabActivity继承于Activity,不过在TabActivity中默认已经集成了TabHost对象。

2. TabHost示例一

本示例将讲述TabHost的基本用法:示例的TabHost中包含3个Tab,并且我们对Tab的切换动作进行了监听。

点击查看:TabHost示例一的源码

2.1 默认Activity的布局

res/layout/main.xml的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

     <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1"/>

        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0"
            android:layout_marginBottom="-4dp"/>

    </LinearLayout>

</TabHost>

说明:注意在该布局中TabHost的id是"@android:id/tabhost",这是android系统默认的tabhost控件的id。在TabActivity中会根据该id获取对应的TabHost对象,然后对其进行操作。 此外,FrameLayout和TabWidget都是使用的android系统默认的id。

2.2 默认Activity的代码

public class TabTest extends TabActivity
    implements TabHost.OnTabChangeListener {

    private static final String TAG_HOME    = "home";
    private static final String TAG_ABOUT   = "about";
    private static final String TAG_CONTACT = "contact";

    private TabHost mTabHost;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mTabHost = getTabHost();
        Resources res = getResources();

        // Create an Intent to launch an Activity for the tab (to be reused)
        Intent intent = new Intent(this, TabHome.class);
        TabSpec spec = mTabHost.newTabSpec(TAG_HOME)
                .setIndicator("HOME", res.getDrawable(R.drawable.ic_tab_home))
                .setContent(intent);
        mTabHost.addTab(spec);

        // Do the same for the other tabs

        intent = new Intent(this, TabAbout.class);
        spec = mTabHost.newTabSpec(TAG_ABOUT)
                .setIndicator("ABOUT", res.getDrawable(R.drawable.ic_tab_about))
                .setContent(intent);
        mTabHost.addTab(spec);


        intent = new Intent(this, TabContact.class);
        spec = mTabHost.newTabSpec(TAG_CONTACT)
                .setIndicator("CONTACT", res.getDrawable(R.drawable.ic_tab_contact))
                .setContent(intent);
        mTabHost.addTab(spec);

        //set tab which one you want open first time 0 or 1 or 2
        mTabHost.setCurrentTab(0);
        mTabHost.setOnTabChangedListener(this);
    }

    ...
}

说明:
(01) TabTest和使用的是main布局。
(02) TabTest通过TabActivity的接口getTabHost()获取TabHost对象,然后根据TabHost对象来添加Tab。
(03) TabHost添加Tab时,会利用到TabHost.TabSpec对象。TabHost对象通过newTabSpec(tagID)创建TabSpec对象,tagID是TabSpec的唯一标识。创建了TabSpec之后,必须要设置调用setIndicator()和setContent()对它进行设置。setIndicator()和setContent()都是重载函数。setIndicator()可以传入"标题"和"图标"(本例就是),也可以直接传入View对象!setContent()支持传入Intent对象,也支持传入viewId。
(04) setCurrentTab()的作用是设置当前Tab标签。
(05) setOnTabChangedListener()的是设置Tab切换的监听器。

2.3 Tab切换监听器

@Override
public void onTabChanged(String tabId) {
    if (tabId.equals(TAG_HOME)) {
        Toast.makeText(this, "HOME selected!", Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(this, "select tab:"+tabId, Toast.LENGTH_SHORT).show();
    }
}

说明:当Tab切换时,会回调onTabChanged(tabId)。onTabChanged(tabId)是切换之后的Tab的唯一标识。

2.4 Tab布局

前面在TabTest中添加了三个Tab标签。这里以TabHome进行说明!实际上,TabHome就是普通的Activity!它的代码如下:

public class TabHome extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tab_home);
    }   
}

TabHost的布局tab_home.xml的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="#0099CC"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <TextView
        android:id="@+id/tv_home"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="Home"
        android:textSize="35sp"
        android:textColor="#ffffff" />

</RelativeLayout>

3. TabHost示例二

示例一中,使用的main.xml包含了Android自带的id。在本示例中,我们将去掉main.xml所包行的id,换一种方式对TabHost进行布局;同时,将TabHost的监听,由Activity修改为布局。

点击查看:TabHost示例二的源码

3.1 默认Activity的布局

res/layout/main.xml的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <include
        android:id="@+id/tab_layout_home"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        layout="@layout/tab_home" /> 

    <include
        android:id="@+id/tab_layout_about"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        layout="@layout/tab_about" /> 

    <include
        android:id="@+id/tab_layout_contact"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        layout="@layout/tab_contact" /> 

</FrameLayout>

说明:main.xml采用FrameLayout布局,它导入了三个布局文件tab_home.xml,tab_about.xml和tab_contact。实际上,这三个布局文件就是"示例一"中TabHost.java,TabAbout.java和TabContact.java三个Tab对应的布局。

3.2 默认Activity的代码

public class TabTest extends TabActivity 
    implements TabHost.OnTabChangeListener {

    private static final String TAG_HOME    = "home";
    private static final String TAG_ABOUT   = "about";
    private static final String TAG_CONTACT = "contact";

    private TabHost mTabHost;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mTabHost = getTabHost();
        Resources res = getResources();
        LayoutInflater.from(this).inflate(R.layout.main, mTabHost.getTabContentView(), true);

        // Create an Intent to launch an Activity for the tab (to be reused)
        TabSpec spec = mTabHost.newTabSpec(TAG_HOME)
                .setIndicator("HOME", res.getDrawable(R.drawable.ic_tab_home))
                .setContent(R.id.tab_layout_home);
        mTabHost.addTab(spec);

        // Do the same for the other tabs

        spec = mTabHost.newTabSpec(TAG_ABOUT)
                .setIndicator("ABOUT", res.getDrawable(R.drawable.ic_tab_about))
                .setContent(R.id.tab_layout_about);
        mTabHost.addTab(spec);


        spec = mTabHost.newTabSpec(TAG_CONTACT)
                .setIndicator("CONTACT", res.getDrawable(R.drawable.ic_tab_contact))
                .setContent(R.id.tab_layout_contact);
        mTabHost.addTab(spec);

        //set tab which one you want open first time 0 or 1 or 2
        mTabHost.setCurrentTab(0);
        mTabHost.setOnTabChangedListener(this);
    }

    ...
}

说明:本例中的TabTest与"示例一中的TabTest"的不同之处在于布局方式,以及TabSpec的setContent()的参数。
(01) 本例的布局仍然使用main.xml。不过示例一中是通过 setContentView(R.layout.main)将main.xml作为TabTest的布局;而本例中是通过LayoutInflater将main.xml作为TabTest的Tab内容的布局(Tab包括"索引标题"和"内容"两部分)。
(02) 本例的setContent是使用的viewID,而示例一中使用的是Intent。

3.3 TabHost的内容布局

虽然例子中包行三个Tab,但它们的实现基本一样。本例以R.id.tab_layout_home对应的布局进行说明。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="#0099CC"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <TextView
        android:id="@+id/tv_home"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="Home"
        android:textSize="35sp"
        android:textColor="#ffffff" />

</RelativeLayout>
by skywang
Previous     Next