Android开发之利用ViewPager实现导航页和滑动标签页效果



ViewPager这个组件是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包含了只有在安卓3.0以上可以使用的api。而viewpager就是其中之一,利用它我们可以做很多事情,从最简单的导航,到页面菜单等等。它在android.support.v4包中。

API:http://developer.android.com/intl/zh-cn/reference/android/support/v4/view/ViewPager.html



1,实现程序导航页(初次使用屏幕左右滑动向导)

main.xml

<?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/viewFlipper1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <!-- PagerTabStrip是用来显示title和下划线,如果是为了实现导航向导效果,不需要这个子标签组件 -->
        <android.support.v4.view.PagerTabStrip
            android:id="@+id/viewPagerTabStrip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top" >
        </android.support.v4.view.PagerTabStrip>
    </android.support.v4.view.ViewPager>

</LinearLayout>

pageguide.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="match_parent"
    android:orientation="vertical" >
    
    

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="38dp"
        android:visibility="gone"
        android:text="立即体验" />

</RelativeLayout>

ViewPageActivity

public class ViewPageActivity extends Activity {

	ViewPager mViewPager;
	//导航页图片资源
	public int[] guides = new int[] { R.drawable.guide_page_1,
			R.drawable.guide_page_2, R.drawable.guide_page_3,
			R.drawable.guide_page_4 };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.viewpage_main);
		mViewPager = (ViewPager) findViewById(R.id.viewFlipper1);
		 initWithPageGuideMode();
	}


	/**
	 * 程序导航页效果
	 */
	public void initWithPageGuideMode() {
		  
		List<View> mList = new ArrayList<View>();
		LayoutInflater inflat = LayoutInflater.from(this);
		//先添加一个最左侧空的view
		View item = inflat.inflate(R.layout.pageguide, null);
		mList.add(item);
		for (int index : guides) {
			item = inflat.inflate(R.layout.pageguide, null);
			item.setBackgroundResource(index);
			mList.add(item);
		}
		//经过遍历,此时item是最后一个view,设置button
		Button btn = (Button) item.findViewById(R.id.button1);
		btn.setVisibility(View.VISIBLE);
		//btn.setOnClickListener(this),设置最后一个页面上button的监听
		//再添加一个最右侧空的view
		item = inflat.inflate(R.layout.pageguide, null);
		mList.add(item);
		//ViewPager最重要的设置Adapter,这和ListView一样的原理
		MViewPageAdapter adapter = new MViewPageAdapter(mList);
		mViewPager.setAdapter(adapter);
		mViewPager.setOnPageChangeListener(adapter);
		mViewPager.setCurrentItem(1);

	}

	/**
	 * 内部类,继承PagerAdapter,当然你也可以直接 new PageAdapter
	 * 
	 * @author yangxiaolong
	 * 
	 */
	class MViewPageAdapter extends PagerAdapter implements OnPageChangeListener {

		private List<View> mViewList;

		public MViewPageAdapter(List<View> views) {
			mViewList = views;
		}

		@Override
		public int getCount() {
			return mViewList.size();
		}

		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {

			return arg0 == arg1;
		}

		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			container.addView(mViewList.get(position), 0);
			return mViewList.get(position);
		}

		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView(mViewList.get(position));
		}

		@Override
		public void onPageScrollStateChanged(int arg0) {

		}

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

		}

		@Override
		public void onPageSelected(int position) {

				if (position == 0) {
					mViewPager.setCurrentItem(1);
				} else if (position == mViewList.size() - 1) {
					mViewPager.setCurrentItem(position - 1);
					Toast.makeText(getApplicationContext(), "页面即将跳转",
							Toast.LENGTH_SHORT).show();
					//应该在这里跳转到MainActivity
					// startActivity(intent);
				}
	

		}

	}

}

ViewPager的适配器是PagerAdapter,它是基类提供适配器来填充页面ViewPager内部,想要使用一个更具体的实现,如FragmentPagerAdapter或FragmentStatePagerAdapter。(google官方建议ViewPager应该和Fragment一起使用)。当我们实现一个PagerAdapter,必须至少覆盖以下方法:

看字面意思就应该能明白init实例化,destroy销毁,count页面数量,不用一一介绍了。


效果图:


这样当我们点击立即体验或是向左滑动图片时就可以直接进入到主界面了~



2,实现标签滑动翻页效果

效果类似于当前流行的微博、新闻客户端顶部导航栏的效果,具体如下:




其实这个效果用ViewPager实现起来so easy!不到200行代码,我直接把代码贴出来,大家一看就明白。

pagetab_main.xml

<?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:background="#FFFFFF"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="fill_parent"
        android:layout_height="40.0dip"
        android:background="#C0C0C0" >

        <TextView
            android:id="@+id/text1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1.0"
            android:gravity="center"
            android:text="新闻"
            android:textColor="#000000"
            android:textSize="20.0dip" />

        <TextView
            android:id="@+id/text2"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1.0"
            android:gravity="center"
            android:text="世界杯"
            android:textColor="#000000"
            android:textSize="20.0dip" />

        <TextView
            android:id="@+id/text3"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1.0"
            android:gravity="center"
            android:text="娱乐"
            android:textColor="#000000"
            android:textSize="20.0dip" />
    </LinearLayout>

    <!-- android:scaleType="matrix" -->

    <ImageView
        android:id="@+id/cursor"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@null"
        android:background="@drawable/select"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewFlipper1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </android.support.v4.view.ViewPager>

</LinearLayout>

ViewPageTabActivity.java

/**
 * @author yangxiaolong
 * 
 */
public class ViewPageTabActivity extends Activity implements OnClickListener {

	private ViewPager mViewPager;// ViewPager定义在xml中
	private ImageView mImageView;// 横向下划线
	private int pWidth;// 图片宽度
	private int offset;// 图片偏移量
	private int currentIndex; // 当前标签位置

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.pagetab_main);
		initViews();
	}

	public void initViews() {

		// step1>>init ViewPager
		mViewPager = (ViewPager) findViewById(R.id.viewFlipper1);
		List<View> mList = new ArrayList<View>();

		// step2>>通过LayoutInflater构建几个子标签页,并存入List集合
		LayoutInflater inflater = LayoutInflater.from(this);
		View view1 = inflater.inflate(R.layout.view1, null);
		View view2 = inflater.inflate(R.layout.view2, null);
		View view3 = inflater.inflate(R.layout.view3, null);
		mList.add(view1);
		mList.add(view2);
		mList.add(view3);
		// step3>>创建自定义PagerAdapter 并添加OnPageChangeListener监听
		MyPagerAdapter adapter = new MyPagerAdapter(mList);
		mViewPager.setAdapter(adapter);
		mViewPager.setOnPageChangeListener(adapter);

		// step4>>导航栏上每一标签项添加onClick监听
		findViewById(R.id.text1).setOnClickListener(this);
		findViewById(R.id.text2).setOnClickListener(this);
		findViewById(R.id.text3).setOnClickListener(this);

		// step5>>初始化横向划线的位置,需要计算偏移量并移动ImageView,有两个方法
		mImageView = (ImageView) findViewById(R.id.cursor);
		// 通过BitmapFactory获得横向划线图片宽度
		Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.select);
		pWidth = bitmap.getWidth();

		// 获取手机屏幕分辨率(宽度)
		Display display = getWindowManager().getDefaultDisplay();
		DisplayMetrics dm = new DisplayMetrics();
		display.getMetrics(dm);
		int screenWidth = dm.widthPixels;

		// 初始化偏移量,计算原理如下
		// 每一个标签页所占:offset+pWidth+offset...[以此类推]
		offset = (screenWidth / 3 - pWidth) / 2;

		// 【方法一】 可以通过Matrix属性设置ImageView组件的偏移
		// 需要xml中ImageView宽度fill_parent,android:scaleType="matrix"
		// Matrix matrix = new Matrix();
		// matrix.postTranslate(offset, 0);
		// mImageView.setImageMatrix(matrix);

		// 【方法二】通过LayoutParams.setMargins属性设置偏移量
		LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
				LayoutParams.WRAP_CONTENT);
		lp.setMargins(offset, 0, 0, 0);
		mImageView.setLayoutParams(lp);
	}

	/**
	 * 自定义PagerAdapter类,构造函数传递List<Views>(标签页View集合),并实现OnPageChangeListener监听
	 * 
	 * @author yangxiaolong
	 * 
	 */
	class MyPagerAdapter extends PagerAdapter implements OnPageChangeListener {

		private List<View> mList;

		public MyPagerAdapter(List<View> views) {
			mList = views;
		}

		@Override
		public int getCount() {
			return mList.size();
		}

		@Override
		public boolean isViewFromObject(View view, Object object) {
			return view == object;
		}

		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView(mList.get(position));
		}

		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			container.addView(mList.get(position), 0);
			return mList.get(position);
		}

		@Override
		public void onPageScrollStateChanged(int arg0) {

		}

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

		}

		@Override
		public void onPageSelected(int position) {

			// 获取每一个标签页所占宽度
			int section = offset * 2 + pWidth;
			// currentIndex为上一次滑动所处标签页位置(0,1,2)
			Animation animation = new TranslateAnimation(
					section * currentIndex, section * position, 0, 0);
			currentIndex = position;
			animation.setDuration(300l);
			animation.setFillAfter(true);// 动画结束后停留在当前所处位置
			mImageView.startAnimation(animation);
			Toast.makeText(ViewPageTabActivity.this,
					"您选择了:" + currentIndex + " 标签页", Toast.LENGTH_SHORT).show();
		}
	}

	@Override
	public void onClick(View v) {
		int index = 0;
		switch (v.getId()) {
		case R.id.text1:
			index = 0;
			break;
		case R.id.text2:
			index = 1;
			break;
		case R.id.text3:
			index = 2;
			break;
		}
		mViewPager.setCurrentItem(index);
	}

}
这就是全部代码,至于说每一个标签页的view布局,就放了ImageView和TextView,就不再贴出来了,各自可以按照需求定制


效果图:



为了能区分出每个标签页,我给每个view都设置了background color颜色。

发布了95 篇原创文章 · 获赞 123 · 访问量 486万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章