Android重写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 stub
        init(context);
    }
 
    public BTViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        init(context);
    }
 
    private void init(Context context) {
        mScroller = new Scroller(context);
        mCurScreen = 0;// 默认设置显示第一个VIEW
    }
 
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
 
        final 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);
    }
 
    @Override
    public void computeScroll() {
        // TODO Auto-generated method stub
        Log.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
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent arg0) {
        // TODO Auto-generated method stub
        Log.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()获取的值是错误的。
ViewPager的getChildCount不对,是因为Viewpager不是根据adapter的数据个数生成对应的数量的View,生成View的个数由setOffscreenPageLimit()指定,默认是生成两个,滑动时,将不可见的上一页destroy掉,新滑到的页通过Adpater的instantiateItem生成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值