一、TabActivity + TabWidget + TabHost.

实现TAB类型界面,首先想到的就是这种方式。但是在API level 13之后官方就不建议使用它了。不过还是在这里简单说一下它的使用吧。

Android 各种实现Tab效果的实现方式_第1张图片

使用它的关键就是布局文件了。需要在布局中添加<TabHost>、<TabWidget>、<FrameLayout>这三个控件,id分别是系统提供的:@android:id/tabhost 、@android:id/tabs 、@android:id/tabcontent 。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TabHost        android:id="@android:id/tabhost"        android:layout_width="match_parent"        android:layout_height="match_parent" >        <RelativeLayout            android:layout_width="match_parent"            android:layout_height="match_parent"            android:orientation="vertical" >            <!-- 可以指定tabwidget的位置    android:layout_alignParentBottom="true" -->            <TabWidget                android:id="@android:id/tabs"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_alignParentBottom="false" >            </TabWidget>            <FrameLayout                android:id="@android:id/tabcontent"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:layout_below="@android:id/tabs" >                <LinearLayout                    android:id="@+id/tab1"                    android:layout_width="match_parent"                    android:layout_height="match_parent"                    android:background="#DEB887"                    android:orientation="vertical" >                </LinearLayout>                <LinearLayout                    android:id="@+id/tab2"                    android:layout_width="match_parent"                    android:layout_height="match_parent"                    android:background="#BCEE68"                    android:orientation="vertical" >                </LinearLayout>                <LinearLayout                    android:id="@+id/tab3"                    android:layout_width="match_parent"                    android:layout_height="match_parent"                    android:background="#7D9EC0"                    android:orientation="vertical" >                </LinearLayout>            </FrameLayout>        </RelativeLayout>    </TabHost></LinearLayout>

一个linearlayout对应一个tab页面的布局。

tabHost = getTabHost();tabHost.addTab(tabHost.newTabSpec("111").setIndicator("", getResources().getDrawable(R.drawable.wuyong)).setContent(R.id.tab1));tabHost.addTab(tabHost.newTabSpec("222").setIndicator("",getResources().getDrawable(R.drawable.gongsunsheng)).setContent(R.id.tab2));tabHost.addTab(tabHost.newTabSpec("333").setIndicator("", getResources().getDrawable(R.drawable.likui)).setContent(R.id.tab3));tabHost.setBackgroundColor(Color.argb(150, 22, 70, 150));tabHost.setCurrentTab(0);tabHost.setOnTabChangedListener(new OnTabChangeListener() {@Overridepublic void onTabChanged(String tabId) {Toast.makeText(FourthActivity.this, tabId, Toast.LENGTH_SHORT).show();}});

二、ViewPager + PageAdapter

目前最常见的tab界面就是使用viewpager来实现了。

先来说一下viewpager的一般使用步骤:

1. 在布局文件中添加viewpager控件

2. 在代码中设置viewpager适配器,该类继承与pagerAdapter或它的子类。必须实现以下四个方法:

(1)getCount()

(2)instantiateItem()

(3)destroyItem()

(4)isViewFromObject()

3. 初始化viewpager控件,设置监听器

4. 设置监听事件(setOnPageChangeListener)

下面看一下这种方式的效果图:

Android 各种实现Tab效果的实现方式_第2张图片

主要的功能代码如下:

private void init() {viewPager = (ViewPager) findViewById(R.id.first_vp);LayoutInflater inflater = LayoutInflater.from(this);View view1 = inflater.inflate(R.layout.first_layout1, null);View view2 = inflater.inflate(R.layout.first_layout2, null);View view3 = inflater.inflate(R.layout.first_layout3, null);list.add(view1);list.add(view2);list.add(view3);viewPager.setAdapter(pagerAdapter);viewPager.setOnPageChangeListener(new OnPageChangeListener() {@Overridepublic void onPageSelected(int arg0) {setDots(arg0);}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageScrollStateChanged(int arg0) {}});}
private PagerAdapter pagerAdapter = new PagerAdapter() {  //官方建议这么写          @Override          public boolean isViewFromObject(View arg0, Object arg1) {              return arg0 == arg1;          }   //返回一共有多少个界面          @Override          public int getCount() {              return list.size();          }  //实例化一个item          @Override          public Object instantiateItem(ViewGroup container, int position) {              container.addView(list.get(position));              return list.get(position);          }  //销毁一个item          @Override          public void destroyItem(ViewGroup container, int position, Object object) {              container.removeView(list.get(position));          }      };

适配器中必须要实现以上的四个方法。

如果只有这几个页面,交互性肯定是不好的,所以需要添加“指示器”,用来标识当前的页面是哪一个!我在这里用点来实现。就像效果图显示的那样。

/** * 初始化底部的点 */private void initDots() {pointLayout = (LinearLayout) findViewById(R.id.point_layout);dots = new ImageView[list.size()];for (int i = 0; i < list.size(); i++) {dots[i] = (ImageView) pointLayout.getChildAt(i);}currentIndex = 0;dots[currentIndex].setBackgroundResource(R.drawable.dian_down);}/** * 当滚动的时候更换点的背景图 */private void setDots(int position) {if (position < 0 || position > list.size() - 1|| currentIndex == position) {return;}dots[position].setBackgroundResource(R.drawable.dian_down);dots[currentIndex].setBackgroundResource(R.drawable.dian);currentIndex = position;}

重点就是页面切换之后,点也要切换。这时候就用到了OnPageChangeListener中的onPageSelected(int arg0)这个方法了。

@Overridepublic void onPageSelected(int arg0) {setDots(arg0);}

三、Fragment + FragmentManager

fragment相信大家在项目中肯定都用过。这个方法主要就是利用fragmentManager对fragment的事务管理功能。

// 三个选项卡private LinearLayout tab1Layout, tab2Layout, tab3Layout;// 默认选中第一个tabprivate int index = 1;// fragment管理类private FragmentManager fragmentManager;// 三个fragmentprivate Fragment tab1Fragment, tab2Fragment, tab3Fragment;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);fragmentManager = getSupportFragmentManager();init();}/** * 初始化控件 */private void init() {tab1Layout = (LinearLayout) findViewById(R.id.tab1_layout);tab2Layout = (LinearLayout) findViewById(R.id.tab2_layout);tab3Layout = (LinearLayout) findViewById(R.id.tab3_layout);tab1Layout.setOnClickListener(this);tab2Layout.setOnClickListener(this);tab3Layout.setOnClickListener(this);//setDefaultFragment();}/** * 设置默认显示的fragment */private void setDefaultFragment() {FragmentTransaction transaction = fragmentManager.beginTransaction();tab1Fragment = new Tab1Fragment();transaction.replace(R.id.content_layout, tab1Fragment);transaction.commit();}/** *切换fragment * @param newFragment */private void replaceFragment(Fragment newFragment) {FragmentTransaction transaction = fragmentManager.beginTransaction();if (!newFragment.isAdded()) {transaction.replace(R.id.content_layout, newFragment);transaction.commit();} else {transaction.show(newFragment);}}/** * 改变现象卡的选中状态 */private void clearStatus() {if (index == 1) {tab1Layout.setBackgroundColor(getResources().getColor(R.color.tab));} else if (index == 2) {tab2Layout.setBackgroundColor(getResources().getColor(R.color.tab));} else if (index == 3) {tab3Layout.setBackgroundColor(getResources().getColor(R.color.tab));}}@Overridepublic void onClick(View v) {clearStatus();switch (v.getId()) {case R.id.tab1_layout:if (tab1Fragment == null) {tab1Fragment = new Tab1Fragment();}replaceFragment(tab1Fragment);tab1Layout.setBackgroundColor(getResources().getColor(R.color.tab_down));index = 1;break;case R.id.tab2_layout:if (tab2Fragment == null) {tab2Fragment = new Tab2Fragment();}replaceFragment(tab2Fragment);tab2Layout.setBackgroundColor(getResources().getColor(R.color.tab_down));index = 2;break;case R.id.tab3_layout:if (tab3Fragment == null) {tab3Fragment = new Tab3Fragment();}replaceFragment(tab3Fragment);tab3Layout.setBackgroundColor(getResources().getColor(R.color.tab_down));index = 3;break;}}

每一个fragment对应一个布局,点击不同的按钮来切换页面。效果如下图:

Android 各种实现Tab效果的实现方式_第3张图片

四、ViewPager + Fragment + FragmentPagerAdapter

如果想使用fragment的时候又想可以左右滑动,就可以使用这种方式。主要的部分就在viewpager的适配器。它的适配器继承FragmentPagerAdapter.

package com.tab.view.demo3;import java.util.ArrayList;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentPagerAdapter;public class FragmentAdapter extends FragmentPagerAdapter {private ArrayList<Fragment> list;public FragmentAdapter(FragmentManager fm, ArrayList<Fragment> list) {super(fm);this.list = list;}@Overridepublic Fragment getItem(int arg0) {return list.get(arg0);}@Overridepublic int getCount() {return list.size();}}

需要传入FragmentManager对象和一个存放fragment的list对象。

/** * 初始化viewpager */private void initViewPager() {viewPager = (ViewPager) findViewById(R.id.third_vp);fragmentsList = new ArrayList<>();Fragment fragment = new Tab1Fragment();fragmentsList.add(fragment);fragment = new Tab2Fragment();fragmentsList.add(fragment);fragment = new Tab3Fragment();fragmentsList.add(fragment);viewPager.setAdapter(new FragmentAdapter(getSupportFragmentManager(),fragmentsList));viewPager.setCurrentItem(0);viewPager.setOnPageChangeListener(this);}

对button添加点击事件。

@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.tab1_tv:viewPager.setCurrentItem(0);break;case R.id.tab2_tv:viewPager.setCurrentItem(1);break;case R.id.tab3_tv:viewPager.setCurrentItem(2);break;}}

我在布局文件中添加了一个imageview作为指示器。如果想第一种tab类型界面的实现方式那样在onPageSelected()方法中进行设置,效果是只能当页面完全切换过来之后才能把指示器移动过去。要想实现滑动页面的时候同时移动指示器,就需要在onPageScrolled()方法中进行设置。

@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) {offset = (screen1_3 - cursorImg.getLayoutParams().width) / 2;Log.d("111", position + "--" + positionOffset + "--"+ positionOffsetPixels);final float scale = getResources().getDisplayMetrics().density;if (position == 0) {// 0<->1lp.leftMargin = (int) (positionOffsetPixels / 3) + offset;} else if (position == 1) {// 1<->2lp.leftMargin = (int) (positionOffsetPixels / 3) + screen1_3 +offset;}cursorImg.setLayoutParams(lp);currentIndex = position;}

onPageScrolled中的三个参数比较重要。第一个参数是position。它的含义是表示当前显示的界面中的第一个界面。意思就是的当滑动的时候,有可能出现两个界面,position指的是左边的界面。第二个参数是positionOffset指的是偏移量的比例,取值范围是[0, 1)。第三个参数是positionOffsetPixels是指偏移的像素值。后两个参数都相对页面(一个page)来说的。

我之前有看到过设置指示器的时候用的前两个参数的,我也试了一下,OK的。不过感觉比较复杂,看了一下官方api,用第三个参数更简单。关键就是理解第一个参数position。用这种方法我只在代码里有两个判断就可以完成了。

效果图如下:

Android 各种实现Tab效果的实现方式_第4张图片

五、Viewpager + PagerTitleStrip/ PagerTabStrip

这种方式没有上一种效果好看,而且标题变动。看一下效果图:

Android 各种实现Tab效果的实现方式_第5张图片

布局文件:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <android.support.v4.view.ViewPager        android:id="@+id/fifth_vp"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center" >        <android.support.v4.view.PagerTabStrip            android:id="@+id/fifth_strip"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="top"            android:background="#7EC0EE"            android:padding="10dip" />    </android.support.v4.view.ViewPager></LinearLayout>

先来说一下PagerTitleStrip和PagerTabStrip的区别:PagerTitleStrip没有指示器,只有标题,且标题没有响应事件;而PagerTabStrip是带有指示器的,当然也有标题,具有相应事件。二者的实现只在布局文件中有区别,只需要把android.support.v4.view.PagerTabStrip改成android.support.v4.viewPagerTitleStrip即可。

代码中需要注意的就是,在适配器中重写getPageTitle(int)方法来显示标题。

PagerAdapter pagerAdapter = new PagerAdapter() {                          //此处省略其他的方法 // 重写此方法即可显示标题  @Override  public CharSequence getPageTitle(int position) {      return titleList.get(position);  }

更多相关文章

  1. Android布局设计中的layout_weight的学习
  2. Android常用布局:线性布局和相对布局
  3. Android 文件布局一些细节备忘
  4. android 虚拟按键遮挡布局
  5. android 线性布局几个属性
  6. Android 启动应用程序方式
  7. Android布局文件的属性值解析
  8. android学习笔记(7)AbsoluteLayout+FrameLayout+RelativeLayout+
  9. android v7兼容包RecyclerView的使用(四)——点击事件的不同方式处

随机推荐

  1. 2016.3.7__HTML 基础_第一天
  2. HTML5--1,html5的生前身后
  3. 大神,你们都在吗???来救救我吧
  4. 如何将每个单词都包含在一个span中,同时保
  5. 长征火箭残骸坠落湖南 砸坏民宅和高压线
  6. 为什么从HTML的select控件中获得的值为空
  7. android 中的线性布局与相对布局
  8. 如何将这些Twitter bootstrap 3导航栏链
  9. Ubuntu的FireFox无法使用HTML5播放器的解
  10. 使用HTML5 canvas做地图(3)图片加载平移放