最近在做开发,UI要求设计成TabLayout的形式,没用过,决定从头到尾跟一遍官网上的教程,英文好的可以直接看官方网站。
网址如下:
http://developer.android.com/resources/tutorials/views/hello-tabwidget.html
现在用中文理一遍,也按照自己的理解添加一些东西,方便今后查阅。
Tab Layout(就翻译为标签布局吧)
为了创建一个标签布局,需要使用一个TabHost和一个TabWidget。TabHost必须作为布局的根基,它包含了用于显示标签的TabWidget和用于显示标签内容的FrameLayout。
有2种方法可以实现标签中内容的切换。一种是使用标签在同一个Activity在切换Views,还有一种是在完全独立的Activity之间切换。(推荐后者)
本教程中也是每个标签单独使用独立的Activity来实现的。
1.创建一个新的工程叫做 HelloTabWidget,这里面创建的Activity叫Tab
2.首先,在工程中创建3个单独的Activity类(也就是在工程的src下面创建3个java类):
ArtistsActivity,AlbumsActivity,SongsActivity.这3个将各自表示一个单独的标签。
现在呢,先使用TextView让每个类显示一个简单的消息。例如:
public class ArtistsActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //前三行都一样,工程自带的,记得在
//最前面导入相关的包
TextView textview = new TextView(this);
//发现一个问题,以前我一直以为每创建一个Activity必须相应地也要创建一个layout文件,现在发现不是这样,也可以按照这个方法,创建一个简单的TextView,把Context设置为this,设置一个文本值,然后再将这个TextView设置为ContentView.这种个人觉得更加方便测试吧。
textview.setText("This is the Artists tab");
setContentView(textview);
}
}
注意:这里并没有使用layout文件,只是创建了一个TextView,设定了一些文本并且将它设置为显示内容。接下来在剩下的2个类中做同样的事情,并且在Manifest文件中声明这3个Activity.
3.每个标签需要一个图标,准确的说每个标签需要两个图标,或者说一个图标的2个版本。一个用于标签被选中的时候,一个用于没被选中的时候。通常建议选中的情况用深色(灰色),没选中的用浅色(白色)。
在这个教程里面,可以直接用原文教程里面的图标。但是最终还是得自己创建。
现在创建一个state-list drawable,标明哪种状态用哪个图标。
1)将图标保存在工程的res/drawable/路径
2)在res/drawable/中创建一个新的XML文件叫ic_tab_artists.xml 加入如下代码
<?
xmlversion
=
"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" /> //state_selected通常就是用于tab
<!-- When not selected, use white-->
<item android:drawable="@drawable/ic_tab_artists_white" />
</selector>
当你的标签状态转换的时候,标签图标就会自动地在所定义好的图片间转换。
4.打开
res/layout/main.xml文件,添加如下代码:
<?
xmlversion
=
"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"
android:padding="5dp">
<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:padding="5dp" />
</LinearLayout>
</TabHost>
这个布局会显示标签,并且提供各个Activity间的导航。
TabHost需要一个TabWidget和一个FrameLayout在里面。它们的位置是垂直的,使用的是线性布局(Linear)。
FrameLayout是每个标签内容所在的地方,现在是空白,因为TabHost会自动地把各个Activity嵌入里面。
注意:TabWidget和FrameLayout各自有其IDs,tabs 和 tabcontent.TabHost必须使用这些名字来索引,需要准确的名字。
5.现在打开Tab.java 并且使其扩展TabActivity:
public class Tabextends TabActivity {
6.使用如下代码来实现onCreate()方法:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Resources res = getResources(); // 获取工程里面的资源的一个实例对象
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);
tabHost.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(2);
}
这个程序为每个标签创建了文本和图标,并且为每个标签分配了Activity。
首先通过getTabHost()获得TabHost的关联,然后,对于每一个标签,创建一个TabHost.TabSpec来定义标签的属性。newTabSpec(String)方法创建一个新的TabHost.TabSpec(),它通过已知的字符标记来指定。对于每一个TabHost.TabSpec,都要调用setIndicator(CharSequence,Drawable)来为标签设定文本和图标,并且调用setContent(Intent)来指定Intent,从而启动对应的Activity.每个TabHost.TabSpec都是通过调用addTab(TabHost.TabSpec)被添加到TabHost里面。
最后,通过指定索引位置,setCurrentTab(int)启动默认被打开的标签。
注意:TabWidget不止一个被用到,因为TabWidget必须一直是TabHost的子集。因此,当一个标签被添加到TabHost,它自动地被添加到TabWidget的子集。
7.现在打开Manifest文件,将NoTitleBar主题添加到Tab的activity中,
<activity android:name=".HelloTabWidget" android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar">
8.运行应用