GestureDetector和SimpleOnGestureListener的使用教程(转)

1. 当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等等,我们知道View类有个View.OnTouchListener内部接口,通过重写他的onTouch(View v, MotionEvent event)方法,我们可以处理一些touch事件,但是这个方法太过简单,如果需要处理一些复杂的手势,用这个接口就会很麻烦(因为我们要自己根据用户触摸的轨迹去判断是什么手势)Android sdk给我们提供了GestureDetector(Gesture:手势Detector:识别)类,通过这个类我们可以识别很多的手势,主要是通过他的onTouchEvent(event)方法完成了不同手势的识别。虽然他能识别手势,但是不同的手势要怎么处理,应该是提供给程序员实现的,因此这个类对外提供了两个接口:OnGestureListener,OnDoubleTapListener,还有一个内部类SimpleOnGestureListener,SimpleOnGestureListener类是GestureDetector提供给我们的一个更方便的响应不同手势的类,这个类实现了上述两个接口(但是所有的方法体都是空的),该类是static class,也就是说它实际上是一个外部类。程序员可以在外部继承这个类,重写里面的手势处理方法。

通过GestureDetector的构造方法可以将SimpleOnGestureListener对象传递进去,这样GestureDetector能处理不同的手势了。

2. 具体用法:

2.1  

private class DefaultGestureListener extends SimpleOnGestureListener{

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            
        }
        /**
         * @param e1 The first down motion event that started the scrolling.
           @param e2 The move motion event that triggered the current onScroll.
           @param distanceX The distance along the X axis(轴) that has been scrolled since the last call to onScroll. This is NOT the distance between e1 and e2.
           @param distanceY The distance along the Y axis that has been scrolled since the last call to onScroll. This is NOT the distance between e1 and e2.
                       无论是用手拖动view,或者是以抛的动作滚动,都会多次触发 ,这个方法在ACTION_MOVE动作发生时就会触发 参看GestureDetector的onTouchEvent方法源码
         * */
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
            return false;
        }
        /**
         * @param e1 第1个ACTION_DOWN MotionEvent 并且只有一个
         * @param e2 最后一个ACTION_MOVE MotionEvent 
         * @param velocityX X轴上的移动速度,像素/秒  
         * @param velocityY Y轴上的移动速度,像素/秒
         * 这个方法发生在ACTION_UP时才会触发 参看GestureDetector的onTouchEvent方法源码
         * 
         * */
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {
            return false;
        }

        @Override
        public void onShowPress(MotionEvent e) {
            
        }
        @Override
        public boolean onDown(MotionEvent e) {
            return false;
        }
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            return false;
        }
        @Override
        public boolean onDoubleTapEvent(MotionEvent e) {
            return false;
        }
        /**
         * 这个方法不同于onSingleTapUp,他是在GestureDetector确信用户在第一次触摸屏幕后,没有紧跟着第二次触摸屏幕,也就是不是“双击”的时候触发
         * */
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return false;
        }
        
    }

 

2.2  public GestureDetector (Context context, GestureDetector.OnGestureListener listener)通过构造方法将手势响应交给手势识别类

2.3  在OnTouchListener的onTouch方法中

private OnTouchListener gestureTouchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return gDetector.onTouchEvent(event);
        }
    };

 

ok,到此为止就结束了

遇到的问题:

1. onFling(***)无法触发

     通过设置 mListView.setLongClickable(true);即可(我处理的是ListView的手势事件),只有这样,view才能够处理不同于Tap(轻触)的hold(即ACTION_MOVE,或者多个ACTION_DOWN),我们同样可以通过layout定义中的android:longClickable来做到这一点。

2. 用户长按手机屏幕,就会触发长按事件,离开屏幕时,就会触发up事件,但是SimpleOnGestureListener没有对longPress事件的up事件对外提供接口

解决办法:

类似于这样,截获up事件,因为所有的都是有OnTouchListener 先获得,然后传递给SimpleOnGestureListener的,这里有一点必须要注意:

截获到up事件,我们进行了处理后,必须要将这个事件再交给SimpleOnGestureListener处理,虽然我们只截获长按事件的up,但是SimpleOnGestureListener对于长按事件的up也做了一些处理,只是没有对外提供接口。

做了什么处理:

if (mInLongPress) {
                mHandler.removeMessages(TAP);
                mInLongPress = false;

}

如果不交给SimpleOnGestureListener处理,那么单击动作也会触发onLongPress方法。

private OnTouchListener gestureTouchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                return gDetector.onTouchEvent(event);
           case MotionEvent.ACTION_UP:
                MyGesture.FlagInfo info = mGesture.getFlagInfo();
                if(info.isConnected==true){
                    int firstVisiblePosition = mListView.getFirstVisiblePosition();
                    View view = mListView.getChildAt(info.position-firstVisiblePosition);
                    if(view!=null){
                        view.setBackgroundResource(R.drawable.listitem_background_blue);
                        info.isConnected = false;
                    }
                }
                return gDetector.onTouchEvent(event);
            case MotionEvent.ACTION_MOVE:
                return gDetector.onTouchEvent(event);
            }
            return false;
            
        }
    };

总结:

1. 点击屏幕上的某项的执行流程  有两种情况,一种是时间很短,一种时间稍长

时间很短:onDown--------》onSingleTapUp--------》onSingleTapConfirmed

时间稍长:onDown--------》onShowPress------》onSingleTapUp--------》onSingleTapConfirmed

2. 长按事件

onDown--------》onShowPress------》onLongPress

3.抛:手指触动屏幕后,稍微滑动后立即松开

onDown-----》onScroll----》onScroll----》onScroll----》………----->onFling

4.拖动

onDown------》onScroll----》onScroll------》onFiling

注意:有的时候会触发onFiling,但是有的时候不会触发,个人理解是人的动作不标准所致。


----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


1. 点击屏幕上的某项的执行流程  有两种情况,一种是时间很短,一种时间稍长

时间很短:onDown--------》onSingleTapUp--------》onSingleTapConfirmed

时间稍长:onDown--------》onShowPress------》onSingleTapUp--------》onSingleTapConfirmed

2. 长按事件

onDown--------》onShowPress------》onLongPress

3.抛:手指触动屏幕后,稍微滑动后立即松开

onDown-----》onScroll----》onScroll----》onScroll----》………----->onFling

4.拖动

onDown------》onScroll----》onScroll------》onFiling

注意:有的时候会触发onFiling,但是有的时候不会触发,个人理解是人的动作不标准所致。


SimpleOnGestureListener

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class MyGesture extends Activity implements OnTouchListener {     
  2.     private GestureDetector mGestureDetector;     
  3.     public MyGesture() {     
  4.         mGestureDetector = new GestureDetector(new MySimpleGesture());     
  5.     }     
  6.     public void onCreate(Bundle savedInstanceState) {     
  7.         super.onCreate(savedInstanceState);     
  8.         setContentView(R.layout.main);     
  9.         TextView tv = (TextView) findViewById(R.id.tv);     
  10.         tv.setOnTouchListener(this);     
  11.         tv.setFocusable(true);     
  12.         tv.setClickable(true);     
  13.         tv.setLongClickable(true);     
  14.     }     
  15.     public boolean onTouch(View v, MotionEvent event) {     
  16.         if (event.getAction() == MotionEvent.ACTION_UP) {     
  17.             Log.i("MyGesture""MotionEvent.ACTION_UP");     
  18.         }     
  19.         return mGestureDetector.onTouchEvent(event);     
  20.     }     
  21.          
  22.     // SimpleOnGestureListener implements GestureDetector.OnDoubleTapListener, GestureDetector.OnGestureListener     
  23.     private class MySimpleGesture extends SimpleOnGestureListener {     
  24.         // 双击的第二下Touch down时触发      
  25.         public boolean onDoubleTap(MotionEvent e) {     
  26.             Log.i("MyGesture""onDoubleTap");     
  27.             return super.onDoubleTap(e);     
  28.         }     
  29.              
  30.         // 双击的第二下Touch down和up都会触发,可用e.getAction()区分     
  31.         public boolean onDoubleTapEvent(MotionEvent e) {     
  32.             Log.i("MyGesture""onDoubleTapEvent");     
  33.             return super.onDoubleTapEvent(e);     
  34.         }     
  35.              
  36.         // Touch down时触发      
  37.         public boolean onDown(MotionEvent e) {     
  38.             Log.i("MyGesture""onDown");     
  39.             return super.onDown(e);     
  40.         }     
  41.              
  42.         // Touch了滑动一点距离后,up时触发     
  43.         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {     
  44.             Log.i("MyGesture""onFling");     
  45.             return super.onFling(e1, e2, velocityX, velocityY);     
  46.         }     
  47.              
  48.         // Touch了不移动一直Touch down时触发     
  49.         public void onLongPress(MotionEvent e) {     
  50.             Log.i("MyGesture""onLongPress");     
  51.             super.onLongPress(e);     
  52.         }     
  53.              
  54.         // Touch了滑动时触发     
  55.         public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {     
  56.             Log.i("MyGesture""onScroll");     
  57.             return super.onScroll(e1, e2, distanceX, distanceY);     
  58.         }     
  59.              
  60.         /*   
  61.          * Touch了还没有滑动时触发   
  62.          * (1)onDown只要Touch Down一定立刻触发   
  63.          * (2)Touch Down后过一会没有滑动先触发onShowPress再触发onLongPress   
  64.          * So: Touch Down后一直不滑动,onDown -> onShowPress -> onLongPress这个顺序触发。   
  65.          */    
  66.         public void onShowPress(MotionEvent e) {     
  67.             Log.i("MyGesture""onShowPress");     
  68.             super.onShowPress(e);     
  69.         }     
  70.     
  71.         /*   
  72.          * 两个函数都是在Touch Down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touch Up时触发   
  73.          * 点击一下非常快的(不滑动)Touch Up: onDown->onSingleTapUp->onSingleTapConfirmed   
  74.          * 点击一下稍微慢点的(不滑动)Touch Up: onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed    
  75.          */      
  76.         public boolean onSingleTapConfirmed(MotionEvent e) {     
  77.             Log.i("MyGesture""onSingleTapConfirmed");     
  78.             return super.onSingleTapConfirmed(e);     
  79.         }     
  80.         public boolean onSingleTapUp(MotionEvent e) {     
  81.             Log.i("MyGesture""onSingleTapUp");     
  82.             return super.onSingleTapUp(e);     
  83.         }     
  84.     }     
  85. }    

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值