Android 各种实现Tab效果的实现方式

一、TabActivity + TabWidget + TabHost.

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

使用它的关键就是布局文件了。需要在布局中添加<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() {
			@Override
			public 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)

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

主要的功能代码如下:

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() {
			@Override
			public void onPageSelected(int arg0) {
				setDots(arg0);
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
			}

			@Override
			public 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)这个方法了。

@Override
			public void onPageSelected(int arg0) {
				setDots(arg0);
			}

三、Fragment + FragmentManager

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

// 三个选项卡
	private LinearLayout tab1Layout, tab2Layout, tab3Layout;
	// 默认选中第一个tab
	private int index = 1;
	// fragment管理类
	private FragmentManager fragmentManager;
	// 三个fragment
	private Fragment tab1Fragment, tab2Fragment, tab3Fragment;

	@Override
	protected 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));
		}
	}

	@Override
	public 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对应一个布局,点击不同的按钮来切换页面。效果如下图:

四、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;
	}
	@Override
	public Fragment getItem(int arg0) {
		return list.get(arg0);
	}
	@Override
	public 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添加点击事件。

@Override
	public 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()方法中进行设置。

@Override
	public 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<->1
			lp.leftMargin = (int) (positionOffsetPixels / 3) + offset;
		} else if (position == 1) {// 1<->2
			lp.leftMargin = (int) (positionOffsetPixels / 3) + screen1_3 +offset;
		}
		cursorImg.setLayoutParams(lp);
		currentIndex = position;
	}

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

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

效果图如下:

五、Viewpager + PagerTitleStrip / PagerTabStrip

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

布局文件:

<?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);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-07 06:15:45

Android 各种实现Tab效果的实现方式的相关文章

使用Fragment实现Tab效果

在上一篇中,我们将了使用ViewPager实现Tab效果.如果没有阅读过,可以点击下面的地址: http://www.cnblogs.com/fuly550871915/p/4849893.html 在这一篇中我们讲一下使用Fragment实现Tab效果,而这种实现方式也是推荐的方式.与用ViewPager实现的效果有一点不同. 一.效果展示 如下图:                                   使用Fragment不支持手指左右滑动,只支持底部按钮的点击来切换.它的中间

Android ActionBar通过Tab进行不同的Fragment之间的交换

ActionBar的使用常见于4.0系统,其Tab的使用挺广泛的. 在ActionBar中添加标签(Tabs),每个标签对应的是一个Fragment,点击不同的Tab时,就会切换到对应的Fragment. 大致的步骤如下: 1.如同TabHost控件,每个tab下需要添加内容,这个内容需要结合fragment来显示,因此需创建fragment类,有几个tab就需要几个继承Fragment的类: 2.将fragment添加至ActionBar Tab上,并添加tab监听: 3.监听内部类需要实现A

Android UI之Tab(ActionBar+Fragment实现)

Fragment和ActionBar都是Android3.0之后出现的,Fragment,碎片,主要是为了支持更多的UI设计在大屏幕设备上,如平板.因为现在设备的屏幕越来越大,使用Fragment可以更灵活的管理视图层次的变化.像Activity一样,可以创建Fragment来包含View,进行布局,但是Fragment必须嵌入在Activity中,不能单独存在,而且一个Activity可以嵌入多个Fragment,同时一个Fragment可以被多个Activity重用.Action Bar被认

fragment做成选项卡,tab效果。 fragment+RadioGroup

fragment做成选项卡,tab效果. fragment+RadioGroup from://http://blog.csdn.net/zimo2013/article/details/12239349 1.Fragment概述 在一个Activity中, Fragment代表UI的一个部分或者一个行为.一个Activity可以结合多个Fragment对象,也可以在多个activity中使用相同Fragment字节码对应的不同对象.一个Fragment对象必须被嵌入在一个主Activity对象

Android开发之动画效果浅析

Android开发之动画效果浅析 请尊重他人的劳动成果,转载请注明出处:Android开发之动画效果浅析 程序运行效果图: Android动画主要包含补间动画(Tween)View Animation.帧动画(Frame)Drawable Animation.以及属性动画Property Animation.下面依次介绍一下各个动画. 1.   补间动画(Tween) Tween动画,通过对View 的内容进行一系列的图形变换 (包括平移.缩放.旋转.改变透明度)来实现动画效果.动画效果的定义可

关于Unity程序在IOS和Android上显示内嵌网页的方式

近期因为有须要在Unity程序执行在ios或android手机上显示内嵌网页.所以遍从网上搜集了一下相关的资料.整理例如以下: UnityWebCore 从搜索中先看到了这个.下载下来了以后发现这个的原理好像是通过调用浏览器内核.然后将网页渲染到mesh的方式完毕的. 但遗憾的是仅仅支持windows桌面版本号.但还是发出来大家假设有须要能够下载  下载地址: http://pan.baidu.com/s/1nt3FVkd unity-webview 这个是在github上找到的. 是一个kei

android Activity切换动画效果

为Activity设置左右进出的效果,可以通过在Mainfest.xml文件中设置主题的方式来实现.还可以使用java代码. 一.设置样式 先看看实现动画的样式: <style name="AnimationRToL" mce_bogus="1" parent="@<span style="color:#ff0000;">android:style/Animation.Activity</span>&quo

巧用Drawable 实现Android UI 元素间距效果

源文地址: 巧用Drawable 实现Android UI 元素间距效果 在大部分的移动UI或者Web UI都是基于网格概念而设计的.这种网格一般都是有一些对其的方块组成.然后它们组合成为一个块. 使用网格这种设计原则能够有助于对齐UI元素,提升UI的一致性,同一时候还能让用户更加easy的获取UI上面包括的内容. 简而言之.网格是一个相当的强大的设计工具. 开发人员在使用网格设计原则的时候须要在UI 元素之间加入一些额外的间距,比方padding.margin或者spacing(依据你的设计方

【转】(转)【Android】Paint的效果研究

转自:http://wpf814533631.iteye.com/blog/1847661 (转)[Android]Paint的效果研究 博客分类: android 在Paint中有很多的属性可以设置,比如可以设置阴影,颜色过滤等等,这些会产生不同的奇妙效果,今天就对各种属性探索一下. 方法一: 1 //设置绘制的颜色,a代表透明度,r,g,b代表颜色值. 2 setARGB(int a,int r,int g,int b); 这个不多说了,还有两个类似的方法,将设置alpha和rgb分割开来了