之前在考虑设计一些客户端时,为了实现Activity下方的类似menu菜单的显示方式,一直傻傻的使用一个footer的布局文件,在这个footer中添加不同的按钮,然后在按钮上添加点击事件,根据点击事件切换到不同的Activity,这几天无聊的查看别人的代码时,才发现自己这种方式的老土,原来Android早就给我们提供了类似的显示方式了,即tabwidget(或者称之为tabhost布局)。
我们的Android手机在很多的app中都使用了它,比如打电话、比如短信等等,今天我就整理下这两天使用的tabhsot布局,并使用两种方式呈现,效果图如下,点击时会有icon颜色变化。
使用TabActivity简单实现
我们的Activity不再继承于Activity而改之继承于tabActivity,并在布局文件中布局上述点击按钮之后的5个显示文字的TextView,布局文件与之前的布局文件并无变化,布局文件代码如下:
XML/HTML代码
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <TextView
- android:id="@+id/t1"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="tab1" />
-
- <TextView
- android:id="@+id/t2"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="tab2" />
-
- <TextView
- android:id="@+id/t3"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="tab3" />
-
- <TextView
- android:id="@+id/t4"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="tab4" />
-
- <TextView
- android:id="@+id/t5"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="tab5" />
-
- </LinearLayout>
在代码部分,我们需要做一些变动,代码不多,所以我先将代码提上来,然后再解释代码的重要地方。
Java代码
- public class TabViewTestActivity extends TabActivity{
- private Context mContext;
- private TabHost mTabHost;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
-
- super.onCreate(savedInstanceState);
- mContext = this;
- mTabHost = getTabHost();
-
- LayoutInflater.from(mContext).inflate(R.layout.main, mTabHost.getTabContentView(), true);
-
- mTabHost.addTab(mTabHost.newTabSpec("A").setIndicator("主题", getResources().getDrawable(R.drawable.theme_menu_theme)).setContent(R.id.t1));
- mTabHost.addTab(mTabHost.newTabSpec("B").setIndicator("壁纸", getResources().getDrawable(R.drawable.theme_menu_wallpaper)).setContent(R.id.t2));
- mTabHost.addTab(mTabHost.newTabSpec("C").setIndicator("背板", getResources().getDrawable(R.drawable.theme_menu_iconbg)).setContent(R.id.t3));
- mTabHost.addTab(mTabHost.newTabSpec("D").setIndicator("锁屏", getResources().getDrawable(R.drawable.theme_menu_screenlock)).setContent(R.id.t4));
- mTabHost.addTab(mTabHost.newTabSpec("E").setIndicator("特效", getResources().getDrawable(R.drawable.theme_menu_effect)).setContent(R.id.t5));
- }
- }
代码中,我们定义一个mTabHost,我们看到了如果按照之前的方式,一个Activity引用布局文件中的布局的话,是使用setContent方法,而这会却是使用的LayoutInflater并在其的第二个参数中将viewGroup指定为getTabContentView。另外我们也看到了我们使用addTab方式给我们的tabWidget添加一个一个的tabSpec。
最后运行效果如下:
名词解释: 既然我们使用tabhost来布局,我有必要对我们将要实现的代码做一个名词解释。
1、tabHost 这个我们可以简单的把它当作整个一张“Activity”,其中包括下面的托盘部分,以及点击托盘的任意按钮托盘上方显示的不同内容,这是最大的一个容器;
2、tabWidget 这个就是托盘部分,主要用来显示不同的栏目,其中包括tabSpec及tabContent;
3、tabSpec就是tabWidget的一个个栏目,你可以为它添加一张icon图片、icon图片下方的栏目名称,另外需要强调的是当用户点击任意 tabSpec时,tabWidget上方将显示内容,这个就是tabContent。
源码下载:使用TabActivity简单实现TabHost显示
我们在上述方式一中简单实现了TabHost的显示,但是我们在代码中主观控制TabHost的方法并不多,甚至在上述代码中,我们都没有见到托盘(TabWidget)的样式控制,所以我们也看到了该方式是将其默认的显示在最上方。但是当我们的需要是将之显示在下方,并且点击一个tab时会出现一些样式变化,比如图片更换等效果,这种方式就不灵活了,所以我们得自己提出自己来自己布局TabHost,使之样式多样化。
自己布局TabHost,样式多样化
在代码开始之前,我们需要对用到的名词进行解释下,如果你已经阅读了方式一,那么请略去!
名词解释: 既然我们使用tabhost来布局,我有必要对我们将要实现的代码做一个名词解释。
1、tabHost 这个我们可以简单的把它当作整个一张“Activity”,其中包括下面的托盘部分,以及点击托盘的任意按钮托盘上方显示的不同内容,这是最大的一个容器;
2、tabWidget 这个就是托盘部分,主要用来显示不同的栏目,其中包括tabSpec及tabContent;
3、tabSpec就是tabWidget的一个个栏目,你可以为它添加一张icon图片、icon图片下方的栏目名称,另外需要强调的是当用户点击任意 tabSpec时,tabWidget上方将显示内容,这个就是tabContent。
既然是自己布局TabHost,我们在布局文件中就需自己一一来布局TabHost,TabWidget等等了,示例中的布局文件tab_main.xml代码如下:
XML/HTML代码
- <?xml version="1.0" encoding="utf-8"?>
- <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/tabhost"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
-
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <TabWidget
- android:id="@android:id/tabs"
- android:layout_width="fill_parent"
- android:layout_height="60dip"
- android:layout_alignParentBottom="true"
- android:background="#424242" >
- </TabWidget>
-
- <FrameLayout
- android:id="@android:id/tabcontent"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
-
- <LinearLayout
- android:id="@+id/theme"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <TextView
- android:id="@+id/theme_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="主题" />
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/wallpaper"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <TextView
- android:id="@+id/wallpaper_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="壁纸" />
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/iconbg"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <TextView
- android:id="@+id/iconbg_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="背板" />
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/screenlock"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <TextView
- android:id="@+id/screenlock_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="锁屏" />
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/effect"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <TextView
- android:id="@+id/effect_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="特效" />
- </LinearLayout>
- </FrameLayout>
- </RelativeLayout>
-
- </TabHost>
从布局文件中,依次可以看到我们的布局文件需要实现的样式了,如果您看到了上面的名词解释再看这个布局文件就很好理解了,另外我们需要注意的两个地方我已经用红色背景画出来了:
1、关于 TabWidget和FrameLayout的id,我们只能这样即使用系统自定义好的id;
2、android:layout_alignParentBottom="true"表示我们的widget是在屏幕的底部显示。
下面我们看java代码,在java代码中,我们无需继承TabActivity,依然和之前的一样继承Activity即可,代码如下:
Java代码
- public class TabDesignActivity extends Activity{
- private Context mContex = this;
- private TabHost mTabHost;
-
- private String TAB1 = "主题";
- private String TAB2 = "壁纸";
- private String TAB3 = "背板";
- private String TAB4 = "锁屏";
- private String TAB5 = "特效";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
-
- super.onCreate(savedInstanceState);
- setContentView(R.layout.tab_main);
-
- mTabHost = (TabHost) findViewById(R.id.tabhost);
- mTabHost.setup();
-
- mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator(getMenuItem(R.drawable.theme_ispressed, TAB1)).setContent(R.id.theme));
- mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator(getMenuItem(R.drawable.wallpaper_ispressed, TAB2)).setContent(R.id.wallpaper));
- mTabHost.addTab(mTabHost.newTabSpec("tab3").setIndicator(getMenuItem(R.drawable.iconbg_ispressed, TAB3)).setContent(R.id.iconbg));
- mTabHost.addTab(mTabHost.newTabSpec("tab4").setIndicator(getMenuItem(R.drawable.screenlock_ispressed, TAB4)).setContent(R.id.screenlock));
- mTabHost.addTab(mTabHost.newTabSpec("tab5").setIndicator(getMenuItem(R.drawable.effect_ispressed, TAB5)).setContent(R.id.effect));
- }
-
- public View getMenuItem(int imgID, String textID){
- LinearLayout ll = (LinearLayout) LayoutInflater.from(mContex).inflate(R.layout.tab_item, null);
- ImageView imgView = (ImageView)ll.findViewById(R.id.icon);
- imgView.setBackgroundResource(imgID);
- TextView textView = (TextView)ll.findViewById(R.id.name);
- textView.setText(textID);
- return ll;
- }
- }
同样我们自己定义个mTabHost,但是这次我们获取mTabHost 是从布局文件中过来的,另外注意的是我们需要写上mTabHost.setup()这么一句代码,这个务必在addTab之前写进去,另外在给tabWidget添加tabSpec时,自己定义了一个getMenuItem方法来实现其图片和文字的显示的,这个方法的使用到的布局文件tab_item.xml如下:
XML/HTML代码
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:gravity="center_horizontal|center_vertical"
- android:orientation="vertical" >
-
- <LinearLayout
- android:id="@+id/ll"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/bg_ispressed"
- android:gravity="center_horizontal|center_vertical"
- android:orientation="vertical" >
-
- <ImageView
- android:id="@+id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <TextView
- android:id="@+id/name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
-
- </LinearLayout>
另外我使用了一个技巧来实现点击tab时换取图片的方式,即在图片文件中加上另一配置文件selector动态切换,关于此可参见【动态改变Tabwidget/tabhost的tab标签图片】:或者下载下面的源码。
源码下载:自己布局TabHost,样式多样化显示