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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章