本文介绍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>