標籤:viewpager android 滑動靈敏
使用ViewPager作為一個頁面進行切換,裡面可以存放很多View,但有時在操作View時不小心滑動一下就有可能跳到下一頁,這並不是我們想要的,這裡就需要重寫ViewPager修改它的滑動條件
程式目錄結構
BTViewPager.java
package com.example.viewpagerdemo;import android.content.Context;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.Scroller;/** * 解決ViewPager滑動過於靈敏,只有滑動距離大於100才滑到另一頁 * * @author Administrator * */public class BTViewPager extends ViewPager {private static final String TAG = "dzt_pager";private static final int MOVE_LIMITATION = 100;// 觸發移動的像素距離private float mLastMotionX; // 手指觸碰螢幕的最後一次x座標private int mCurScreen;private Scroller mScroller; // 滑動控制項public BTViewPager(Context context) {super(context);// TODO Auto-generated constructor stubinit(context);}public BTViewPager(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubinit(context);}private void init(Context context) {mScroller = new Scroller(context);mCurScreen = 0;// 預設設定顯示第一個VIEW}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubfinal int action = event.getAction();final float x = event.getX();switch (action) {case MotionEvent.ACTION_DOWN:Log.d(TAG, "[BTViewPager->]onTouchEvent ACTION_DOWN");mLastMotionX = x;break;case MotionEvent.ACTION_MOVE:Log.d(TAG, "[BTViewPager->]onTouchEvent ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.d(TAG, "Item = " + getCurrentItem() + " count = "+ getChildCount());if (Math.abs(x - mLastMotionX) < MOVE_LIMITATION) {// snapToDestination(); // 跳到指定頁snapToScreen(getCurrentItem());return true;}break;default:break;}Log.d(TAG, "[BTViewPager->]onTouchEvent--end");return super.onTouchEvent(event);}@Overridepublic void computeScroll() {// TODO Auto-generated method stubLog.d(TAG, "[BTViewPager->]computeScroll");super.computeScroll();if (mScroller.computeScrollOffset()) {Log.d(TAG,"[BTViewPager->]computeScroll x = " + mScroller.getCurrX());scrollTo(mScroller.getCurrX(), mScroller.getCurrY());invalidate();}}/** * 根據滑動的距離判斷移動到第幾個視圖 */public void snapToDestination() {final int screenWidth = getWidth();final int destScreen = (getScrollX() + screenWidth / 2) / screenWidth;Log.d(TAG, "[BTViewPager->]snapToDestination screenWidth = "+ screenWidth + " destScreen = " + destScreen);snapToScreen(destScreen);}/** * 滾動到制定的視圖 * * @param whichScreen * 視圖下標 */public void snapToScreen(int whichScreen) {// whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() -// 1));if (getScrollX() != (whichScreen * getWidth())) {final int delta = whichScreen * getWidth() - getScrollX();Log.d(TAG, "[BTViewPager->]snapToScreen-whichScreen = "+ whichScreen + " delta = " + delta + " scrollX = "+ getScrollX());mScroller.startScroll(getScrollX(), 0, delta, 0,Math.abs(delta) * 2);mCurScreen = whichScreen;invalidate();}}/** * 用於攔截手勢事件的,每個手勢事件都會先調用這個方法。Layout裡的onInterceptTouchEvent預設傳回值是false, * 這樣touch事件會傳遞到childview控制項 ,如果返回false子控制項可以響應,否則了控制項不響應,這裡主要是攔截子控制項的響應, * 對ViewGroup不管傳回值是什麼都會執行onTouchEvent */@Overridepublic boolean onInterceptTouchEvent(MotionEvent arg0) {// TODO Auto-generated method stubLog.d(TAG, "[BTViewPager->]onInterceptTouchEvent");final int action = arg0.getAction();final float x = arg0.getX();switch (action) {case MotionEvent.ACTION_DOWN:Log.d(TAG, "onInterceptTouchEvent---ACTION_DOWN ");mLastMotionX = x;break;case MotionEvent.ACTION_MOVE:Log.d(TAG, "onInterceptTouchEvent---ACTION_MOVE ");break;case MotionEvent.ACTION_UP:Log.d(TAG, "onInterceptTouchEvent---ACTION_UP ");break;default:break;}return super.onInterceptTouchEvent(arg0);}}只要是在onTouchEvent的UP中處理滑動的條件
if (Math.abs(x - mLastMotionX) < MOVE_LIMITATION) {// snapToDestination(); // 跳到指定頁snapToScreen(getCurrentItem());return true;}只有滑動的距離大於100才進行上下頁處理,否則就停在當前頁,當前頁使用getCurrentItem()擷取,有一點要注意在ViewPager中getChildCount()擷取的值是錯誤的,不清楚是什麼原因,在ViewGroup中是有效,這個可能要查看ViewPager源碼才能弄清楚是什麼原因,有知道的朋友可以告知我!
完整Demo:http://download.csdn.net/detail/deng0zhaotai/7384637