牛骨文教育服务平台(让学习变的简单)

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界面就完成了。是不是很简单。以下我贴出源代码,下载不用积分,只希望对大家有点帮助。

代码下载