Android 實現縱向瀏覽的ViewPager

要實現自定義ViewPager,就要自己重寫ScollerView,寫一個繼承ViewGroup的自定義控件。

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

public class MyScrollView extends ViewGroup {
	//解析手勢的工具
	private GestureDetector detector;
	//這是一個用於計算
	private Scroller myScoller;
	//記錄down事件時的Y座標
	private int startY;
	//記錄當前的id值
	private int currentId;
	private Context context;
	//記錄是否是快速滑動
	private boolean isFling;

	//重寫構造方法
	public MyScrollView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		this.context = context;
		initView();
	}

	private void initView() {
		// TODO Auto-generated method stub
		myScoller = new Scroller(context);
		detector = new GestureDetector(new OnGestureListener() {

			@Override
			public boolean onSingleTapUp(MotionEvent e) {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public void onShowPress(MotionEvent e) {
				// TODO Auto-generated method stub

			}
			//滑動事件
			@Override
			public boolean onScroll(MotionEvent e1, MotionEvent e2,
					float distanceX, float distanceY) {
				// TODO Auto-generated method stub
				scrollBy(0, (int) distanceY);
				return false;
			}

			@Override
			public void onLongPress(MotionEvent e) {
				// TODO Auto-generated method stub

			}
			//快速滑動事件
			@Override
			public boolean onFling(MotionEvent e1, MotionEvent e2,
					float velocityX, float velocityY) {
				isFling = true;
				if (velocityY < 0 && currentId > 0) {
					currentId--;
				} else if (velocityY > 0 && currentId < getChildCount() - 1) {
					currentId++;
				}
				moveToDest(currentId);
				return false;
			}

			@Override
			public boolean onDown(MotionEvent e) {
				// TODO Auto-generated method stub
				return false;
			}
		});
	}

	//對子View進行佈局
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		// TODO Auto-generated method stub
		for (int i = 0; i < getChildCount(); i++) {
			View v = getChildAt(i);
			v.layout(0, -getHeight() * i, getWidth(), getHeight() * (1 - i));
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		detector.onTouchEvent(event);
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			startY = (int) event.getY();
			break;

		case MotionEvent.ACTION_MOVE:

			break;
		case MotionEvent.ACTION_UP:
			//UP事件發生時,先判斷是否是快速滑動,若是快速滑動,則GestureDetector會去處理
			if (!isFling) {
				//若不是快速滑動,則判斷滑動到了哪裏,向上滑動,或向下滑動
				int disY = (int) (event.getY() - startY);
				if (disY > getHeight() / 2) {
					currentId++;
				} else if (disY < -getHeight() / 2) {
					currentId--;
				}
				moveToDest(currentId);
			}
			break;
		}
		return true;
	}

	/**
	 * 滑動到目標ID的方法
	 * @param id
	 */
	private void moveToDest(int id) {
		// TODO Auto-generated method stub
		id = id >= 0 ? id : 0;
		id = id < getChildCount() ? id : (getChildCount() - 1);
		int disY = -getScrollY() - id * getHeight();
		//給 myScoller設置初始座標和目標座標
		myScoller.startScroll(0, getScrollY(), 0, disY);
		currentId = id;
		invalidate();
	}

	/**
	 * ViewGroup調用invalidate()方法時,會調用該方法
	 */
	@Override
	public void computeScroll() {
		// myScoller會固定時間計算當前位置
		if (myScoller.computeScrollOffset()) {
			scrollTo(0, myScoller.getCurrY());
			//invalidate方法會重複調用computeScroll方法,直到到達myScoller的目標座標爲止
			invalidate();
		}
		super.computeScroll();
	}
}

然後將需要添加的視圖利用addView方法,添加到MyScollerView中就可以了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章