在iphone开发中貌似有个UITabBarController,UITabBarController在底部,也有对应的切换效果,都封装好了。但是在android的中,这个东西它在顶部。
当标签控制的Activity跳转到下一级Activity时,标签栏也会被覆盖,这样用户不能从下一级页面判断是从哪一个标签控制的Activity切换过来的,而在iphone中UITabBarController控制器很好地处理了这个问题,当用户push到下一级页面时,标签始终存在,并且标签选中状态不会改变,只有切换标签时才会改变标签的选中状态。由于受iphone的毒害,我做android项目时,也想实现这样的效果,经过网上查阅资料,在众多网友高手的启示下,终于实现我想要的效果,好了,废话少说,下面将我的实现方式如详细介绍,供有同样需求的网友参考!
一、实现原理及效果图
利用ActivityGroup + GridView + ViewFlipper 实现选项卡,
首页,当点击下一页按钮时,跳转到下一级页面
下一级页面如下所示:从图中看以清楚地看到,这一页面是从第一个标签选项卡控制的Activity跳转过来的
二,实现步骤
1)首先创建基于ActivityGroup的一个基类,在该类中,实现了切换Activity的功能,代码如下:
public class BaseGroupActivity extends ActivityGroup {
//显示日志tag
private static final String TAG = "MyTag";
//Tab栈管理
protected TabStack stack = new TabStack();
protected ViewFlipper containerFlipper;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(keyCode == KeyEvent.KEYCODE_BACK){
if(!stack.isEmpty()){
back();
}else{
finish();
}
return true;
}
return super.onKeyDown(keyCode, event);
}
public void switchActivity(String id,Intent intent,int inAnimation,int outAnimation) {
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Window window = getLocalActivityManager().startActivity(id, intent);
View v = window.getDecorView();
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
LayoutParams param = new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
v.setLayoutParams(param);
try {
containerFlipper.setInAnimation(AnimationUtils.loadAnimation(this,inAnimation));
containerFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,outAnimation));
} catch (NotFoundException e) {
e.printStackTrace();
}
containerFlipper.addView(v);
containerFlipper.showNext();
if(inAnimation == R.anim.push_right_in){
containerFlipper.removeViewAt(stack.size());
}
stack.push(id);
System.out.println("pust:" + id);
Log.i(TAG, "pust = " + id);
}
public void back(){
if(stack.size() > 1){
containerFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_in));
containerFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,R.anim.push_right_out));
containerFlipper.showPrevious();
containerFlipper.removeViewAt(stack.size() - 1);
stack.pop();
}else
this.finish();
}
public void popSome(String id){
int sum = stack.getTheSumToPop(id);
containerFlipper.removeViews(stack.size() - sum, sum - 1);
stack.popSome(id);
containerFlipper.setDisplayedChild(containerFlipper.getChildCount() - 1);
}
}
2)然后,创建一个基于TabActivity,核心代码如下:
public class MainActivity extends TabActivity {
private TabHost mHost;
private GridView gvTopBar;
private TabBarItemAdapter tabBarImgAdapter;
/** 标签item图片信息 **/
int[] imgIds = { R.drawable.icon_home,R.drawable.icon_search,
R.drawable.icon_shopcart,R.drawable.icon_myebuy, R.drawable.icon_info};
/** 标签item标题文字信息 **/
int[] strIds = {R.string.tab_home,R.string.tab_search,
R.string.tab_shopcart,R.string.tab_myebuy,R.string.tab_info};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.ebuy_main);
fillViews();
setupIntent();
}
//填充标签栏item
private void fillViews(){
gvTopBar = (GridView) this.findViewById(R.tab.gridview);
gvTopBar.setNumColumns(imgIds.length);// 设置每行列数
gvTopBar.setSelector(new ColorDrawable(Color.TRANSPARENT));// 选中的时候为透明色
gvTopBar.setGravity(Gravity.CENTER);// 位置居中
gvTopBar.setVerticalSpacing(0);// 垂直间隔
int width = this.getWindowManager().getDefaultDisplay().getWidth()
/ imgIds.length;
tabBarImgAdapter = new TabBarItemAdapter(this, imgIds, width, 30, R.drawable.tab_sel_top, strIds);
gvTopBar.setAdapter(tabBarImgAdapter);
gvTopBar.setOnItemClickListener(new ItemClickEvent());// 项目点击事件
}
//设置对应标签的Activity
private void setupIntent() {
this.mHost = getTabHost();
TabHost localTabHost = this.mHost;
localTabHost.addTab(buildTabSpec(TabIds.TAB_HOME, R.string.tab_home,
new Intent(this,HomeTabGroup.class)));
localTabHost.addTab(buildTabSpec(TabIds.TAB_SEARCH, R.string.tab_search,
new Intent(this,SearchTabGroup.class)));
localTabHost.addTab(buildTabSpec(TabIds.TAB_SHOPCART, R.string.tab_shopcart,
new Intent(this,ShopcartTabGroup.class)));
localTabHost.addTab(buildTabSpec(TabIds.TAB_MYEBUY, R.string.tab_myebuy,
new Intent(this,MyEbuyTabGroup.class)));
localTabHost.addTab(buildTabSpec(TabIds.TAB_INFO, R.string.tab_info,
new Intent(this,InfoTabGroup.class)));
}
private TabHost.TabSpec buildTabSpec(String tag, int resLabel,
final Intent content) {
return this.mHost
.newTabSpec(tag)
.setIndicator(getString(resLabel))
.setContent(content);
}
//标签item设置监听器,响应标签item点击事件
class ItemClickEvent implements OnItemClickListener {
public void onItemClick(AdapterView arg0, View arg1, int arg2,
long arg3) {
SwitchActivity(arg2);
}
}
//根据tag值,切换标签
void SwitchActivity(int id) {
tabBarImgAdapter.SetFocus(id);
switch (id) {
case 0:
this.mHost.setCurrentTabByTag(TabIds.TAB_HOME);
break;
case 1:
this.mHost.setCurrentTabByTag(TabIds.TAB_SEARCH);
break;
case 2:
this.mHost.setCurrentTabByTag(TabIds.TAB_SHOPCART);
case 3:
this.mHost.setCurrentTabByTag(TabIds.TAB_MYEBUY);
break;
case 4:
this.mHost.setCurrentTabByTag(TabIds.TAB_INFO);
break;
default:
break;
}
}
}
3)在第二步时,setupIntent()方法,设置标签控制的Activity,这里我举一例子代码予以说明,其它类似。该Activity继承在第一步我们创建的基类,代码如下:
public class HomeTabGroup extends BaseGroupActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_content);
fillViews();
}
private void fillViews(){
containerFlipper = (ViewFlipper) findViewById(R.tab.content);
Intent intent = new Intent(this,HomeActivity.class);
switchActivity(EbuyConstant.TabIds.TAB_HOME_view,intent,-1,-1);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return this.getLocalActivityManager().getCurrentActivity().onTouchEvent(event);
}
}
HomeTabGroup parent = (HomeTabGroup)getParent();
Intent intent = new Intent(this, ProductListActivity.class);
intent.putExtra(IntentFlags.FLAG_PRODUCTLIST, ProductListActivity.FLAG_INTENT_PRODUCTLIST);
parent.switchActivity(TabIds.TAB_HOME, intent, R.anim.push_left_in, R.anim.push_left_out);
通过上面的步骤,实现了我iphone样式的标签功能。到此,java代码实现部分已经完成,下面把代码中用到的配置文件也一一介绍,包括动画、页面布局,网友只需要把图片资源和文字信息作相应更改即可。
三、xml配置文件
1)tab.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"
android:background="@color/bg"
>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="0.0dip"
android:layout_weight="1.0" />
<TabWidget
android:id="@android:id/tabs"
android:visibility="gone"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.0" />
<LinearLayout android:layout_width="fill_parent"
android:layout_height="49dip"
android:gravity="center_vertical"
android:layout_gravity="bottom"
android:background="@drawable/tab_bg">
<GridView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+tab/gridview"
android:fadingEdgeLength="5dip"
android:fadingEdge="vertical"/>
LinearLayout>
LinearLayout>
2)tab_content.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"
android:background="@color/bg"
>
<ViewFlipper
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+tab/content"
>
ViewFlipper>
LinearLayout>
3)ebuy_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"
>
<include layout="@layout/tab" android:id="@+login/tab"/>
TabHost>
3)home.xml文件
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">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="40dip"
android:background="@drawable/top_bg"
android:gravity="center"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tab_home"
style="@style/TopBarText"
/>
LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button android:id="@+id/next_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="下一页">
Button>
LinearLayout>
LinearLayout>
4)动画文件,这里只以两个动画为例,其它类似
push_left_in.xml文件如下:
xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0"
android:duration="500" />
<alpha android:fromAlpha="1.0" android:toAlpha="1.0"
android:duration="500" />
set>
push_left_out.xml文件如下:
xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="-100%p"
android:duration="500" />
<alpha android:fromAlpha="1.0" android:toAlpha="1.0"
android:duration="500" />
set>
初次写android博客,有不到之处请高手指出。