Android底部tab切換界面的實現比較簡單,可以利用TabHost直接實現,實現方式網上資源很多。那么除了用特定的組件來實現tab外能不能自己寫代碼實現呢。答案是肯定的。還有一個很常用的問題,就是不同的tab界面能否實現不同的標題欄?這個需求在項目中經常碰到,本文將講敘Android底部tab切換界面的實現以及它與標題欄的結合。實現效果圖如下:

上圖就是我們要實現的效果圖,切換到不同的界面有不同的顯示標題。不多說直接上代碼。
首先當然是布局文件,先實現標題欄布局。新建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的底層原理
- 仿美團商品選購下拉菜單實現