Android底部tab切换界面的实现比较简单,可以利用TabHost直接实现,实现方式网上资源很多。那么除了用特定的组件来实现tab外能不能自己写代码实现呢。答案是肯定的。还有一个很常用的问题,就是不同的tab界面能否实现不同的标题栏?这个需求在项目中经常碰到,本文将讲叙Android底部tab切换界面的实现以及它与标题栏的结合。实现效果图如下:
![](https://box.kancloud.cn/2016-04-08_570771b44e74c.jpg)
上图就是我们要实现的效果图,切换到不同的界面有不同的显示标题。不多说直接上代码。
首先当然是布局文件,先实现标题栏布局。新建title.xml文件
~~~
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#111111" >
<TextView
android:id="@+id/title_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:textColor="#ffffff"
android:textSize="18dp"
android:visibility="gone" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="#ffffff"
android:textSize="22dp"/>
<TextView
android:id="@+id/title_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:textColor="#ffffff"
android:textSize="18dp"
android:visibility="gone" />
</RelativeLayout>
~~~
以上实现了标题栏的布局,title_left和title_right分别是标题栏的左、右按钮,默认情况下将其设置为不可见。
接下来就是tab栏布局文件的实现,新建一个tab.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_bottom"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#efefef"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/nav_search"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:orientation="vertical" >
<View
android:id="@+id/nav_search_color"
android:layout_width="fill_parent"
android:layout_height="3dp"
android:background="@color/nav_pressed"
android:duplicateParentState="true" />
<ImageView
android:id="@+id/nav_search_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp"
android:scaleType="center"
android:src="@drawable/icon_square_nor1" />
<TextView
android:id="@+id/nav_search_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="搜 索"
android:textColor="@color/nav_pressed"
android:textSize="10sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/nav_home_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:orientation="vertical" >
<View
android:id="@+id/nav_home_color"
android:layout_width="fill_parent"
android:layout_height="3dp"
android:background="@color/nav_normal" />
<ImageView
android:id="@+id/nav_home_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp"
android:scaleType="center"
android:src="@drawable/icon_home_nor" />
<TextView
android:id="@+id/nav_home_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="主 页"
android:textColor="@color/nav_text_normal"
android:textSize="10sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/nav_selfinfo_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:orientation="vertical" >
<View
android:id="@+id/nav_selfinfo_color"
android:layout_width="fill_parent"
android:layout_height="3dp"
android:background="@color/nav_normal" />
<ImageView
android:id="@+id/nav_selfinfo_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp"
android:scaleType="center"
android:src="@drawable/icon_selfinfo_nor" />
<TextView
android:id="@+id/nav_selfinfo_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="个人信息"
android:textColor="@color/nav_text_normal"
android:textSize="10sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/nav_mess_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:orientation="vertical" >
<View
android:id="@+id/nav_mess_color"
android:layout_width="fill_parent"
android:layout_height="3dp"
android:background="@color/nav_normal" />
<ImageView
android:id="@+id/nav_mess_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp"
android:scaleType="center"
android:src="@drawable/icon_meassage_nor" />
<TextView
android:id="@+id/nav_mess_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:gravity="center_horizontal"
android:text="信 息"
android:textColor="@color/nav_text_normal"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout>
~~~
只需要看一部分就可以了,一个LinearLayout包括着一个View,ImageView和TextView,其中View是底部栏上方的那条横线。ImagView与TextView不用说,就是底部栏的头像和头像下方的文字。
主布局文件就是利用include把标题栏与底部栏融合到一起,并用ViewPage来显示不同页面。布局如下:
~~~
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<include
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
layout="@layout/title" />
<include
android:id="@+id/tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
layout="@layout/tab" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/top"
android:layout_above="@id/tab"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" >
</android.support.v4.view.ViewPager>
</LinearLayout>
</RelativeLayout>
~~~
接下来的实现我们用到了Fragment,四个页面分别加载了四个Fragment。所以要写四个不同的fragment.xml,这个根据不同需求进行编写。那重头戏来了,下面贴出主程序。代码有点长,但不用担心,其实现原理很简单。
~~~
public class MainActivity extends FragmentActivity {
private ViewPager m_vp;
private int navIndex = 0;
private int currIndex = 0;
private Fragment mfragment1;
private Fragment mfragment2;
private Fragment mfragment3;
private Fragment mfragment4;
private List<Fragment> fragmentList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTitle();
getView();
initFragments();
}
/**
* 初始化标题,并加载四个Fragment
*/
public void initTitle(){
((TextView) findViewById(R.id.title)).setText("搜索");
((TextView)findViewById(R.id.title_left)).setVisibility(View.INVISIBLE);
((TextView)findViewById(R.id.title_right)).setVisibility(View.INVISIBLE);
}
private void getView(){
m_vp = (ViewPager)findViewById(R.id.viewpager);
mfragment1 = new Fragment1();
mfragment2 = new Fragment2();
mfragment3 = new Fragment3();
mfragment4 = new Fragment4();
}
/**
* 初始化页面
*/
public void initFragments()
{
fragmentList = new ArrayList<Fragment>();
fragmentList.add(mfragment1);
fragmentList.add(mfragment2);
fragmentList.add(mfragment3);
fragmentList.add(mfragment4);
findViewById(R.id.nav_search).setOnClickListener(new MyOnClickListener(0));
findViewById(R.id.nav_home_layout).setOnClickListener(new MyOnClickListener(1));
findViewById(R.id.nav_selfinfo_layout).setOnClickListener(new MyOnClickListener(2));
findViewById(R.id.nav_mess_layout).setOnClickListener(new MyOnClickListener(3));
setNavState(navIndex, 0);
m_vp.setAdapter(new MyViewPagerAdapter(getSupportFragmentManager()));
m_vp.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
Log.i("zhi", arg0+"");
switch (arg0) {
case 0:
if (navIndex != 0){
// 点击之前如果就是这个控件,不变化
setNavState(navIndex, 0);
navIndex = 0;
}
break;
case 1:
if (navIndex != 1){
// 点击之前如果就是这个控件,不变化
setNavState(navIndex, 1);
navIndex = 1;
}
break;
case 2:
if (navIndex != 2){
// 点击之前如果就是这个控件,不变化
setNavState(navIndex, 2);
navIndex = 2;
}
break;
case 3:
if (navIndex != 3){
// 点击之前如果就是这个控件,不变化
setNavState(navIndex, 3);
navIndex = 3;
}
break;
default:
break;
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
private void setNavState(int before, int after) {
// 点击之前的那个按钮恢复正常
switch (before) {
case 0:
findViewById(R.id.nav_search_color).setBackgroundResource(R.color.nav_normal);
((ImageView )findViewById(R.id.nav_search_img)).setImageResource(R.drawable.icon_square_nor);
((TextView) findViewById(R.id.nav_search_text)).setTextColor(getResources().getColor(R.color.nav_text_normal));
break;
case 1:
findViewById(R.id.nav_home_color).setBackgroundResource(R.color.nav_normal);
((ImageView )findViewById(R.id.nav_home_img)).setImageResource(R.drawable.icon_home_nor);
((TextView) findViewById(R.id.nav_home_text)).setTextColor(getResources().getColor(R.color.nav_text_normal));
((TextView)findViewById(R.id.title_right)).setVisibility(View.INVISIBLE);
break;
case 2:
findViewById(R.id.nav_selfinfo_color).setBackgroundResource(R.color.nav_normal);
((ImageView )findViewById(R.id.nav_selfinfo_img)).setImageResource(R.drawable.icon_selfinfo_nor);
((TextView) findViewById(R.id.nav_selfinfo_text)).setTextColor(getResources().getColor(R.color.nav_text_normal));
((TextView)findViewById(R.id.title_left)).setVisibility(View.INVISIBLE);
break;
case 3:
findViewById(R.id.nav_mess_color).setBackgroundResource(R.color.nav_normal);
((ImageView )findViewById(R.id.nav_mess_img)).setImageResource(R.drawable.icon_meassage_nor);
((TextView) findViewById(R.id.nav_mess_text)).setTextColor(getResources().getColor(R.color.nav_text_normal));
break;
default:
break;
}
// 点击到的那个显示状态
switch (after) {
case 0:
findViewById(R.id.nav_search_color).setBackgroundResource(R.color.nav_pressed);
((ImageView )findViewById(R.id.nav_search_img)).setImageResource(R.drawable.icon_square_nor1);
((TextView) findViewById(R.id.nav_search_text)).setTextColor(getResources().getColor(R.color.nav_text_pressed));
((TextView) findViewById(R.id.title)).setText("搜索");
break;
case 1:
findViewById(R.id.nav_home_color).setBackgroundResource(R.color.nav_pressed);
((ImageView )findViewById(R.id.nav_home_img)).setImageResource(R.drawable.icon_home_nor1);
((TextView) findViewById(R.id.nav_home_text)).setTextColor(getResources().getColor(R.color.nav_text_pressed));
((TextView)findViewById(R.id.title_right)).setVisibility(View.VISIBLE);
((TextView)findViewById(R.id.title_right)).setText("设置");
((TextView) findViewById(R.id.title)).setText("主页");
break;
case 2:
findViewById(R.id.nav_selfinfo_color).setBackgroundResource(R.color.nav_pressed);
((ImageView )findViewById(R.id.nav_selfinfo_img)).setImageResource(R.drawable.icon_selfinfo_sel1);
((TextView) findViewById(R.id.nav_selfinfo_text)).setTextColor(getResources().getColor(R.color.nav_text_pressed));
((TextView)findViewById(R.id.title_left)).setVisibility(View.VISIBLE);
((TextView)findViewById(R.id.title_left)).setText("返回");
((TextView) findViewById(R.id.title)).setText("个人信息");
break;
case 3:
findViewById(R.id.nav_mess_color).setBackgroundResource(R.color.nav_pressed);
((ImageView )findViewById(R.id.nav_mess_img)).setImageResource(R.drawable.icon_meassage_nor1);
((TextView) findViewById(R.id.nav_mess_text)).setTextColor(getResources().getColor(R.color.nav_text_pressed));
((TextView) findViewById(R.id.title)).setText("信息");
break;
default:
break;
}
}
public class MyViewPagerAdapter extends FragmentPagerAdapter{
public MyViewPagerAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
@Override
public Fragment getItem(int arg0) {
return fragmentList.get(arg0);
}
@Override
public int getCount() {
return fragmentList.size();
}
}
public class MyOnClickListener implements View.OnClickListener {
private int index = 0;
public MyOnClickListener(int i) {
index = i;
currIndex=i;
}
@Override
public void onClick(View v) {
m_vp.setCurrentItem(index);
}
};
}
~~~
相信大家都能看懂,这里简单讲解一下。程序首先运行initTitle对标题栏进行初始化,在getView中定义一个list装上四个Fragment,方便之后的调用。initFragments()方法主要是完成对界面的加载和监听不到的触发事件。这里用到了Viewpage进行页面的切换。首先是监听底部栏按钮的的点击事件,点击的按钮触发ViewPage的setCurrentItem方法加载不同的ViewPage页。ViewPage对页面的变化进行监听,不同页面调用不同的setNavState()方法。最后就只剩下了解setNavState的作用了。setNavState方法用于对底部按钮的图标、字体状态还有标题栏的显示状态进行动态变化,switch(before)是操作之前点击的那个按钮的状态,switch(after)是操作之后点击的按钮的状态。
到这里主函数就讲完了。接下来要做是的就定义自己的Fragement,让它们去实现我们想要的界面。至此我们一个自定义的底tab界面就完成了。是不是很简单。以下我贴出源代码,下载不用积分,只希望对大家有点帮助。
[代码下载](http://download.csdn.net/detail/u014486880/8733109)
- 前言
- Android底部tab与标题栏相结合
- Android免费获取短信验证码
- android中Handler的源码分析
- 详解Fragment的传值问题
- 详谈gson解析
- android新控件之toolbar,floatingActionButton,SnackBar,CollapsingToolbarLayout
- android自定义控件
- 浅谈android的线程池
- Android的消息处理机制,AsyncTask源码解析
- IPC——android进程间通信
- CoCos2d_android入门所需知道的一切
- Cocos2d_android你所需要知道的一切(下)
- Activity你需要知道的一切
- Activity启动过程源码分析
- Data Binding Guide——google官方文档翻译(上)
- Data Binding Guide——google官方文档翻译(下)
- android TextView实现跑马灯效果
- android中生成excel
- Volley源码解析
- LayoutInflater源码解析
- android发送邮件
- android测试工具MonkeyRunner--google官网翻译
- android View绘制源码分析
- Android中Window添加View的底层原理
- 仿美团商品选购下拉菜单实现