zoukankan      html  css  js  c++  java
  • Android重写ViewPager改动滑动灵敏度

        使用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 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()获取的值是错误的,不清楚是什么原因,在ViewGroup中是有效的,这个可能要查看ViewPager源代码才干弄清楚是什么原因。有知道的朋友能够告知我。
    完整Demo:http://download.csdn.net/detail/deng0zhaotai/7384637

  • 相关阅读:
    jQuery插件开发入门
    [转]JS学习总结-技巧、方法、细节
    JS无法获取display为none的隐藏元素的宽度和高度的解决方案
    vuejs2.0运用原生js实现简单的拖拽元素功能
    HTML5效果:Canvas 实现圆形进度条并显示数字百分比
    git常用命令总结以及用github来展示你的前端页面
    jQuery 对AMD的支持(Require.js中如何使用jQuery)
    vue+springboot上传和下载附件功能
    springboot+vue实现文件上传
    Spring boot+Vue全栈开发---Spring Boot文件上传
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/8283975.html
Copyright © 2011-2022 走看看