为了创建一个选项卡的UI,你需要使用一个TabHost和一个TabWidget,TabHost必须是布局文件的根节点,它包含了为了显示选项卡的TabWidget和一个用于显示选项内容的FrameLayout
你可以用一或两种方法实现你的选项卡内容:在用一个Activity中用选项卡来在视图之间切换,或者用用选项卡来改变所有的分离的Activity。你根据你的需求来使用你想在程序中的方法,但是如果每个选项卡提供一个独特的用户Activity,那么为每个选项卡实现独立的Activity是有意义的,所有你最好在你的离散群里管理应用程序,要好过使用大量的应用程序和布局文件。
在这个例子中,你可以创建一个为每个单独的Activity创建选项卡来创建一个选项卡UI
1、开始一个新的工程,叫做HelloTabWidget
2、第一,创建三个独立的Activity程序在你的工程中:ArtistsActivity,AlbumsActivity,和SongsActivity,他们每个代表一个单独的选项卡,现在用TextView来没每个程序显示一个简单的信息,比如:
- package org.hualang.tabwidget;
- import android.app.Activity;
- import android.os.Bundle;
- import android.widget.TextView;
- public class AlbumsActivity extends Activity {
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- TextView textview = new TextView(this);
- textview.setText("This is the Albums tab");
- setContentView(textview);
- }
- }
- package org.hualang.tabwidget;
- import android.app.Activity;
- import android.os.Bundle;
- import android.widget.TextView;
- public class SongsActivity extends Activity {
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- TextView textview = new TextView(this);
- textview.setText("This is the Songs tab");
- setContentView(textview);
- }
- }
- package org.hualang.tabwidget;
- import android.app.Activity;
- import android.os.Bundle;
- import android.widget.TextView;
- public class ArtistsActivity extends Activity {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- TextView textview = new TextView(this);
- textview.setText("This is the Artists tab");
- setContentView(textview);
- }
- }
注意这个例子中不需要布局文件,只需要创建一个TextView,并且为文本赋值即可。重复创建三个类似的Activity,并且要在AndroidManifest.xml文件中注册,否则报错
3、你需要为每个选项卡设置一个icon,每个icon,你可以有两个版本,一个是当选项卡被选中的时候,另一个是当选项卡未被选中的时候。一般设计来说,建议当被选中的时候用灰色,的那个未被选中的时候用白色,比如
你可以拷贝这两张图片来做实验用
现在创建一个状态图片列表来制定每个选项卡不同状态的时候所指定的图片
①把图排尿保存在res/drawable/目录下
②在res/drawable/目录下创建一个名为ic_tab_artists.xml文件,并且插入如下信息
- <?xml version="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"/>
- <!-- When not selected ,use white -->
- <item android:drawable="@drawable/ic_tab_artists_white"/>
- </selector>
上面这个文件,当选项卡的状态改变的时候,选项卡就会自动的在两种已经定义的图片之间切换
4、打开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"
- 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布局,为了使TabWidget和FrameLayout的位置处于垂直方向,需要一个LinearLayout,FrameLayout是每个选项卡内容的地方,之所以那里的内容是空的是因为在TahHost中将自动为每个Activity嵌入
注意,TabWidget和FrameLayout元素的ID标签和tabcontent元素,这些名称必须使用,因为TahHost检索他们的引用,它恰好期望的是这些名字
6、编写HelloTabWidget。继承TabWidget
- package org.hualang.tabwidget;
- import android.app.TabActivity;
- import android.content.Intent;
- import android.content.res.Resources;
- import android.os.Bundle;
- import android.widget.TabHost;
- public class HelloTabWidget extends TabActivity {
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- Resources res = getResources(); // Resource object to get Drawables
- 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_drawable))
- .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_drawable))
- .setContent(intent);
- tabHost.addTab(spec);
- intent = new Intent().setClass(this, SongsActivity.class);
- spec = tabHost.newTabSpec("songs").setIndicator("Songs",
- res.getDrawable(R.drawable.ic_tab_drawable))
- .setContent(intent);
- tabHost.addTab(spec);
- tabHost.setCurrentTab(2);
- }
- }
运行结果:
接下来贴出本例运行的效果图:
ImageAdapter是本实例的关键之一,它继承于BaseAdapter,并加入一些自定义的方法。ImageAdapter的源码如下:
- package com.ActivityGroupDemo;
- import android.content.Context;
- import android.graphics.drawable.ColorDrawable;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.GridView;
- import android.widget.ImageView;
- /**
- *
- * @author GV
- *
- */
- public class ImageAdapter extends BaseAdapter {
- private Context mContext;
- private ImageView[] imgItems;
- private int selResId;
- public ImageAdapter(Context c,int[] picIds,int width,int height,int selResId) {
- mContext = c;
- this.selResId=selResId;
- imgItems=new ImageView[picIds.length];
- for(int i=0;i<picIds.length;i++)
- {
- imgItems[i] = new ImageView(mContext);
- imgItems[i].setLayoutParams(new GridView.LayoutParams(width, height));//设置ImageView宽高
- imgItems[i].setAdjustViewBounds(false);
- //imgItems[i].setScaleType(ImageView.ScaleType.CENTER_CROP);
- imgItems[i].setPadding(2, 2, 2, 2);
- imgItems[i].setImageResource(picIds[i]);
- }
- }
- public int getCount() {
- return imgItems.length;
- }
- public Object getItem(int position) {
- return position;
- }
- public long getItemId(int position) {
- return position;
- }
- /**
- * 设置选中的效果
- */
- public void SetFocus(int index)
- {
- for(int i=0;i<imgItems.length;i++)
- {
- if(i!=index)
- {
- imgItems[i].setBackgroundResource(0);//恢复未选中的样式
- }
- }
- imgItems[index].setBackgroundResource(selResId);//设置选中的样式
- }
- public View getView(int position, View convertView, ViewGroup parent) {
- ImageView imageView;
- if (convertView == null) {
- imageView=imgItems[position];
- } else {
- imageView = (ImageView) convertView;
- }
- return imageView;
- }
- }
SetFocus(int)这个方法是个关键点,即实现选中的效果。例如有ABCD4个Item,其中C被选中了,那么除C以外的Item都被设置为未被选中的样式,而C则设置为选中的样式。
接下来就开始写主Activity,主Activity包含GridView控件,名为gvTopBar,有2点是需要注意一下的。
- SetNumColumns():必须要使用setNumColumns来设置列数,因为这个GridView只有一行,即所有的Item都在同一行,Item数量即为列数。
- setSelector(new ColorDrawable(Color.TRANSPARENT)):把系统默认选中的背景色透明化,因为我们已经在BaseAdapter中加入了SetFocus()来改变选中的样式。
- package com.ActivityGroupDemo;
- import android.app.Activity;
- import android.app.ActivityGroup;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.graphics.Color;
- import android.graphics.drawable.ColorDrawable;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.View;
- import android.view.Window;
- import android.view.ViewGroup.LayoutParams;
- import android.widget.AdapterView;
- import android.widget.GridView;
- import android.widget.LinearLayout;
- import android.widget.Toast;
- import android.widget.AdapterView.OnItemClickListener;
- /**
- *
- * @author GV
- *
- */
- public class ActivityGroupDemo extends ActivityGroup {
- private GridView gvTopBar;
- private ImageAdapter topImgAdapter;
- public LinearLayout container;// 装载sub Activity的容器
- /** 顶部按钮图片 **/
- int[] topbar_image_array = { R.drawable.topbar_home,
- R.drawable.topbar_user, R.drawable.topbar_shoppingcart,
- R.drawable.topbar_note };
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- gvTopBar = (GridView) this.findViewById(R.id.gvTopBar);
- gvTopBar.setNumColumns(topbar_image_array.length);// 设置每行列数
- gvTopBar.setSelector(new ColorDrawable(Color.TRANSPARENT));// 选中的时候为透明色
- gvTopBar.setGravity(Gravity.CENTER);// 位置居中
- gvTopBar.setVerticalSpacing(0);// 垂直间隔
- int width = this.getWindowManager().getDefaultDisplay().getWidth()
- / topbar_image_array.length;
- topImgAdapter = new ImageAdapter(this, topbar_image_array, width, 48,
- R.drawable.topbar_itemselector);
- gvTopBar.setAdapter(topImgAdapter);// 设置菜单Adapter
- gvTopBar.setOnItemClickListener(new ItemClickEvent());// 项目点击事件
- container = (LinearLayout) findViewById(R.id.Container);
- SwitchActivity(0);//默认打开第0页
- }
- class ItemClickEvent implements OnItemClickListener {
- public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
- long arg3) {
- SwitchActivity(arg2);
- }
- }
- /**
- * 根据ID打开指定的Activity
- * @param id GridView选中项的序号
- */
- void SwitchActivity(int id)
- {
- topImgAdapter.SetFocus(id);//选中项获得高亮
- container.removeAllViews();//必须先清除容器中所有的View
- Intent intent =null;
- if (id == 0 || id == 2) {
- intent = new Intent(ActivityGroupDemo.this, ActivityA.class);
- } else if (id == 1 || id == 3) {
- intent = new Intent(ActivityGroupDemo.this, ActivityB.class);
- }
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- //Activity 转为 View
- Window subActivity = getLocalActivityManager().startActivity(
- "subActivity", intent);
- //容器添加View
- container.addView(subActivity.getDecorView(),
- LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
- }
- }
主Activity的布局XML文件源码如下:
- <?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">
- <RelativeLayout android:layout_height="fill_parent"
- android:layout_width="fill_parent">
- <GridView android:layout_height="wrap_content" android:id="@+id/gvTopBar"
- android:layout_alignParentTop="true" android:layout_width="fill_parent"
- android:fadingEdgeLength="5dip" android:fadingEdge="vertical">
- </GridView>
- <LinearLayout android:id="@+id/Container"
- android:layout_below="@+id/gvTopBar" android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- </LinearLayout>
- </RelativeLayout>
- </LinearLayout>