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,这三个帮助类介绍到这里,谢谢阅读。

更多相关文章

  1. Android传感器概述(五)
  2. Android(安卓)内存缓存框架 LruCache 的源码分析
  3. Android-使用HttpURLConnection实现多线程下载
  4. 如何让Android程序支持安装到SD卡(APP2SD)
  5. AsyncTask 完全解析
  6. Android通知栏-Notification(通知消息)
  7. Unity和Android相互通信
  8. 美团热修复 Robust 方案接入(一)
  9. Android中的属性动画理解

随机推荐

  1. Android(安卓)软键盘imeOptions(Done)的用
  2. Activity对象的onCreate方法真是Android
  3. 我的android 第8天 - 单元测试
  4. Android之防火墙功能的实现
  5. Android与HTML+JS交互入门
  6. 细谈Android应用架构
  7. Android网络请求心路历程
  8. Android(安卓)设置投影效果
  9. Android知识体系结构概览
  10. 用cmd 命令更改Android(安卓)的默认虚拟