#手势#

什么是手势

其实就是 onTouchEvent 中用,去识别判断出用户当前操作是个啥行为,是双击,长按,滑动,缩放,抛掷这些,然后做相应的操作,业务。

###识别手势 > * 如何确定手势操作时间 ?(长按多久,双击间隔多久) > * 如何确定手势距离 ?(移动长度大于多少算移动,小于多少算点击) > * 如何确定连续加速度 ?(滑动加减速,抛掷后续补全)

当然系统有在ViewConfiguration 里面有设定这些操作的默认值,但是自身去识别具体那个手势,处理,逻辑太复杂,庞大,划不来。

想明白手势,首先需要有基础的事件分发知识,知道VIEW TREE 对于事件的处理,怎么去持有消耗一个事件,避免使用时候出现,“为啥我这个手势没有被触发啊,没有回调啊?”这些问题。

###系统提供方法 系统在API 1就添加了手势类GestureDetector 支持识别手势:

  public interface OnGestureListener {
    boolean onDown(MotionEvent e);

    void onShowPress(MotionEvent e);

    boolean onSingleTapUp(MotionEvent e);

    boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);


    void onLongPress(MotionEvent e);


    boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
}

public interface OnDoubleTapListener {

    boolean onSingleTapConfirmed(MotionEvent e);


    boolean onDoubleTap(MotionEvent e);


    boolean onDoubleTapEvent(MotionEvent e);
}

对于如何在ontouchEvent中判断出这些手势可以参考 grepcode中源码,不复杂,繁琐些。主要讲使用,

###GestureDetector怎么用(listener方式) 1. 添加回调listenter”OnGestureListener”或者“OnDoubleTapListener”根据需要监控的手势 2. 在你自定的view的onToucheEvent调用对应listener类似

    public boolean onTouchEvent( MotionEvent event ) {
       boolean gestureIntercept = mGestureDetector.onTouchEvent(event);
       return gestureIntercept  ||  super.onTouchEvent( event );
    }
  1. 根据你要监控手势的层级,在listener各层级手势中返回true(接受事件),比如你要监听双击,那想当然的单击时间就必须接受,以此类推。

  2. tips: 有时候只是想简单的监控一个手势,实现”OnGestureListener”需要填写太多方法,感觉繁琐,系统有提供一个GestureDetector的内部类SimpleOnGestureListener已经实现了对应借口,简单的extends,复写相关方法就好了,代码量少很多。

###GestureDetector怎么用(handler方式) 1. 通过构造器添加handler。 2. 在handler里面处理message

private static final int SHOW_PRESS = 1;

private static final int LONG_PRESS = 2;

private static final int TAP = 3;

这种方式用的很少,有特殊需求可以参考。

###V4对于低版本的适配 可以参考系统V4对于低版本的实现 GestureDetectorCompat,(源码中以compat结尾的都是Android系统自身对于低版本的适配类),使用方式和GestureDetector一样,都是丢入一个”OnGestureListener”和“OnDoubleTapListener”回调。 > * 奇怪的是GestureDetector API 1就添加了,为什么还有一个GestureDetectorCompat做版本适配尼,可能有更好的兼容,后面有发现补充

GestureDetectorCompat中包含两个子类,GestureDetectorCompatImplBaseGestureDetectorCompatImplJellybeanMr2,分别是适配低版本,和API 17以上的版本,前者是处理事件判断出对应手势,后者是使用GestureDetector来实现内部判断。后面开发中如果需要在手势中 做些特别处理,可以复制GestureDetectorCompatImplBase实现做基础,然后修改。

###关于加速度 VelocityTracker使用

  1. onTouchEvent中 初始化

         if (mVelocityTracker == null) {
                   mVelocityTracker = VelocityTracker.obtain();
             }
             mVelocityTracker.addMovement(ev);
    
  2. 设置大小范围 可以参考

      mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity();
      mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity();
    
  3. 在onTouchEvent的ActionUp里面获取加速完后的XY移动量。

         //计算
         mVelocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
         //获取是那根手指和手指ID
         final int upIndex = ev.getActionIndex();
         final int id1 = ev.getPointerId(upIndex);
         //获取加速完后的偏移量XY
         final float x1 = mVelocityTracker.getXVelocity(id1);
         final float y1 = mVelocityTracker.getYVelocity(id1);
    

###缩放手势 ScaleGestureDetector

GestureDetector实现完全相同,使用也一样,都有“OnScaleGestureListener”和“SimpleOnScaleGestureListener”,也在V4中有适配类 ScaleGestureDetectorCompat,参照GestureDetector使用学习就好了。


党洁