Android UI 滚动、手势、速度的三个帮助类学习

Android提供了滚动帮助类Scroller,手势帮助类GestureDetector和速度帮助类VelocityTracker,之所以叫帮助类,是因为它们和正常的UI显示没有直接的关系,它们只是提供一些算法帮助,帮助我们得到想要的坐标值或者事件监听。下面分别讲一下这三个帮助类。


Scroller:

Scoller是自动滚动的帮助类,用到的场合是让某个控件自动滚动。比如有这么一个需求,我想让一个按钮5秒之内从(100,120)这个坐标滚动到(200,300)这个坐标。我们可以自己写代码,比如计算出每隔100毫秒应该滚动多少,然后用一个计时器或者直接用一个递归在5秒内让这个按钮不断执行draw方法,可以实现但是显然比较麻烦。那Scroller就是帮助我们实现这个功能的类,它帮我们提供了一种算法计算出了每次draw的时候应该滚动到哪里而不需要我们自己去计算了。

Scroller的用法比较简单:

在初始化控件的时候就可以初始化Scroller,然后在需要自动滚动的时候调用startScroll方法,然后在View的computeScroll方法里(这个方法会在View每次draw的时候调用),调用Scroller的computeScrollOffset方法,这个方法就是实现了刚才说的计算并返回滚动是不是应该结束的boolean,并且把计算结果赋值到Scroller的currentX和currentY中。然后在View的computeScroll里直接调用scrollTo滚动到这点就行了。滚动完以后,调用invalidate,然后又会调用到draw方法,然后又会调用到computeScroll方法,接着又会调用Scroller的computeScrollOffset方法。

这里View的computeScroll方法和内部调用的invalidate方法形成了间接递归。

@Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            invalidate();
        }
    }


GestureDetector:

关于手势,我们可以在view的onTouchEvent里做一些处理,比如根据用户两次点击的间隔判断是不是双击,比如可以计算用户抬起手指时的速度以进行一些其它操作,比如down的时候记下手指的坐标然后手指在view上移动的时候相减得到手指滑动了多少距离,当然要考虑一些多点触控。

上面的方式当然可以,但是同样也是比较麻烦。于是GestureDetector被设计出来了,他帮我们进行了上述的操作,我们只要实现相关监听方法就行了。

GestureDetector的用法如下:

初始化代码:

mGestureDetector = new GestureDetector(new GestureListener()); 
mGestureDetector.setOnDoubleTapListener(new DoubleTapListener());
这两个参数的类都是自己实现的相关监听者类,实现了监听者接口,

//OnGestureListener监听
	private class GestureListener implements GestureDetector.OnGestureListener{

		
		// 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发   
		public boolean onDown(MotionEvent e) {
			Log.i("MyGesture", "onDown");   
//	        Toast.makeText(MainActivity.this, "onDown", Toast.LENGTH_SHORT).show();   
	        System.out.println("---------------------------onDown----------------");
			return false;
		}

		/*  
	     * 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发  
	     * 注意和onDown()的区别,强调的是没有松开或者拖动的状态  
	     * 
	     * 而onDown也是由一个MotionEventACTION_DOWN触发的,但是他没有任何限制,
	     * 也就是说当用户点击的时候,首先MotionEventACTION_DOWN,onDown就会执行,
	     * 如果在按下的瞬间没有松开或者是拖动的时候onShowPress就会执行,如果是按下的时间超过瞬间
	     * (这块我也不太清楚瞬间的时间差是多少,一般情况下都会执行onShowPress),拖动了,就不执行onShowPress。
	     */
		public void onShowPress(MotionEvent e) {
			Log.i("MyGesture", "onShowPress");   
//	        Toast.makeText(MainActivity.this, "onShowPress", Toast.LENGTH_SHORT).show();  
	        System.out.println("---------------------------onShowPress----------------");
		}

		// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发   
		///轻击一下屏幕,立刻抬起来,才会有这个触发
		//从名子也可以看出,一次单独的轻击抬起操作,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以这个事件 就不再响应
		public boolean onSingleTapUp(MotionEvent e) {
			Log.i("MyGesture", "onSingleTapUp");   
//	        Toast.makeText(MainActivity.this, "onSingleTapUp", Toast.LENGTH_SHORT).show();   
	        System.out.println("---------------------------onSingleTapUp----------------");
	        return true;   
		}

		// 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发   
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			Log.i("MyGesture", "onScroll:"+(e2.getX()-e1.getX()) +"   "+distanceX);   
//	        Toast.makeText(MainActivity.this, "onScroll", Toast.LENGTH_LONG).show();   
	        System.out.println("---------------------------onScroll----------------"+"onScroll:"+(e2.getX()-e1.getX()) +"   "+distanceX);
	        return true;   
		}

		// 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发   
		public void onLongPress(MotionEvent e) {
			 Log.i("MyGesture", "onLongPress");   
//		     Toast.makeText(MainActivity.this, "onLongPress", Toast.LENGTH_LONG).show();   
		     System.out.println("---------------------------onLongPress----------------");
		}

		// 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发   
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			Log.i("MyGesture", "onFling");   
//	        Toast.makeText(MainActivity.this, "onFling", Toast.LENGTH_LONG).show();   
	        System.out.println("---------------------------onFling----------------");
			return true;
		}
	};


	//OnDoubleTapListener监听
	private class DoubleTapListener implements GestureDetector.OnDoubleTapListener{

		public boolean onSingleTapConfirmed(MotionEvent e) {
			Log.i("MyGesture", "onSingleTapConfirmed");   
//	        Toast.makeText(MainActivity.this, "onSingleTapConfirmed", Toast.LENGTH_LONG).show();  
	        System.out.println("---------------------------onSingleTapConfirmed----------------");
			return true;
		}

		public boolean onDoubleTap(MotionEvent e) {
			Log.i("MyGesture", "onDoubleTap");   
//	        Toast.makeText(MainActivity.this, "onDoubleTap", Toast.LENGTH_LONG).show();  
	        System.out.println("---------------------------onDoubleTap----------------");
			return true;
		}

		public boolean onDoubleTapEvent(MotionEvent e) {
			Log.i("MyGesture", "onDoubleTapEvent");   
//	        Toast.makeText(MainActivity.this, "onDoubleTapEvent", Toast.LENGTH_LONG).show();  
	        System.out.println("---------------------------onDoubleTapEvent----------------"+e.getAction());
			return true;
		}
	};

然后还有一点非常重要,就是在onTouch或者onInterceptTouchEvent等触摸时会调用的方法中加上截获相关事件(记得吗, GestureDetector知识个帮助类,只提供算法帮助)。

	/* 
     * 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector 
     * 来分析是否有合适的callback函数来处理用户的手势 
     */  
	public boolean onTouch(View v, MotionEvent event) {
		boolean result=mGestureDetector.onTouchEvent(event);
		System.out.println("result---------------------:"+result);
		return result;
	}
	

以上代码参照了  http://blog.csdn.net/harvic880925/article/details/39520901  。


VelocityTracker:

提供了速度的相关计算帮助。比如我想知道我此时的手指移动速度,如果自己计算的话,肯定会根据我手指移动的距离除以消耗的时间,当然要考虑其它很多因素,那VelocityTracker就是帮我们干这个的。

VelocityTracker的用法也很简单,如下:

也是在onTouch或者onInterceptTouchEvent等触摸时会调用的方法中加上截获相关事件:

mVelocityTracker.addMovement(event);

然后在ACTION_MOVE中:

verTracker.computeCurrentVelocity(1000, mMaxVelocity);
float velocityX = verTracker.getXVelocity(mPointerId);
float velocityY = verTracker.getYVelocity(mPointerId);

就得到了当前x轴和y轴的滑动速度。


OK,这三个帮助类介绍到这里,谢谢阅读。

你可能感兴趣的:(Android,UI)