• android手势监听GestureDetector接口详解


    文章由多出组合而成,它们来自:

    http://blog.sina.com.cn/s/blog_8edee36301010kv9.html

    http://blog.csdn.net/xiezhenxiang/article/details/6659506

    http://384444165.iteye.com/blog/1502761

    android的手势识别是android更人性化,让我们的操作更简单, 其实我们日常应用中不少地方都使用了手势识别方法 比如 2011年那么火的 愤怒的小鸟 中的 发射武器, uc 游览器 的左右滑动功能,这都是可以使用android的手势识别来实现。如果想要实现提高我们app 的用户体验,更具有可操作性,那这时android的GestureDetector 就派上用场了 , 我们先开看看GestureDetector这个类的api 给我们提供了哪些操作

    下面是GestureDetector 这个类的概括情况

    根据 MotionEvent事件检测各种手势. GestureDetector.OnGestureListener 回调函数用于通知用户发生的手势动作。该类仅处理MotionEvent 事件中的触摸事件(不处理轨迹球事件)。 使用该类的方法如下:

    1:首先需要在初始化的时候创建GestureDetector对象实例

    接口 OnDoubleTapListener 手势监听器 用于双击时发出通知

    接口 OnGestureListener 手势监听器 用于发送手势操作时发生通知 如 拖动,长按,按下,弹起 等手势操作

    类 SimpleOnGestureListener GestureDetector的扩展类 这个类的作用是当我们只想使用部分手势时, 而非全部的时候 就可以继承这个类

    GestureDetector 还有几个公共方法 如下

    boolean isLongpressEnabled() 判定是否允许长点击
    boolean onTouchEvent(MotionEventev)
    分析给定的动作事件,如果满足条件,就触发GestureDetector.OnGestureListener 中提供的回调函数。
    void setIsLongpressEnabled(boolean isLongpressEnabled)
    设置是否允许长按。如果允许长按,当用户按下并保持按下状态时, 将收到一个长按事件,同时不再接收其它事件;如果禁用长按, 当用户按下并保持按下状态然后再移动手指时,将会接收到滚动事件。 长按默认为允许。
    void setOnDoubleTapListener(GestureDetector.OnDoubleTapListeneronDoubleTapListener)
    设置双击及其相关手势的监听器。

    OnGestureListener 接口 的公共方法 如果你想在你的app view中实现下面这些手势操作的话 继承该接口 并实现下面这些方法即可

    abstract boolean onDown(MotionEvente)
    当轻触手势按下屏幕 时发生的事件.
    abstract boolean onFling(MotionEvent e1, MotionEvente2, float velocityX, float velocityY)
    快速滑动后抬起事件的通知.
    abstract void onLongPress(MotionEvente)
    长按时的通知事件
    abstract boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    滑动屏幕时通知事件 为了方便提供了X轴和Y轴上的滚动距离.
    abstract void onShowPress(MotionEvente)
    当用户长点击后抬起时通知事件
    abstract boolean onSingleTapUp(MotionEvente)
    当轻触手势抬起屏幕时发生的事件.

    OnDoubleTapListener 接口的公共方法

    abstract boolean onDoubleTap(MotionEvente)
    双击发生时的通知。
    abstract boolean onDoubleTapEvent(MotionEvente)
    双击手势过程中发生的事件,包括按下、移动和抬起事件。
    abstract boolean onSingleTapConfirmed(MotionEvente)
    发生确定的单击时执行。

    onSingleTapUp(MotionEvent)不同, 该事件在探测器确定用户单击后没有发生导致双击事件的第二次单击时发生。

    在实际应用中 我们根据我们所需要的功能实现不同的接口 或者 继承自SimpleOnGestureListener 类 只实现部分个人需要的方法 就可以了

    直接看代码 GameSurfaceView类

    package yxqz.com;

    import android.content.Context;

    import android.content.DialogInterface;

    import android.graphics.Bitmap;

    import android.graphics.BitmapFactory;

    import android.graphics.Canvas;

    import android.graphics.Color;

    import android.util.Log;

    import android.view.GestureDetector;

    import android.view.GestureDetector.OnGestureListener;

    import android.view.MotionEvent;

    import android.view.SurfaceHolder;

    import android.view.SurfaceView;

    import android.view.SurfaceHolder.Callback;

    import android.widget.Toast;

     

    /**

    * android 手势识别

    * @author mahaile

    *

    */

    public class GameSurfaceView extends SurfaceView implements Callback,OnGestureListener{

     private String TAG="GameView";

    boolean flag; //线程标示位 当为false时停止刷新界面

    SurfaceHolder surfaceHolder;

    GameViewThread gameViewThread;

    float x=0,y=0;

    int stat=0; //手势识别状态标示

    private GestureDetector gd; // 手势

    Context context;

    int width,height;

    Bitmap bitmap_role;

    public GameSurfaceView(Context context) {

    super(context);

    this.context=context;

    surfaceHolder=this.getHolder();

    surfaceHolder.addCallback(this); //添加回调

    //设置焦点 如果不设置焦点的话 在该界面下 点击触摸屏是无效的 默认为false

    setFocusableInTouchMode(true);

    bitmap_role=BitmapFactory.decodeResource(getResources(), R.drawable.role);

    gd=new GestureDetector(this); //创建手势监听对象

    }

    public void onDraw(Canvas canvas){

    canvas.drawColor(Color.BLACK);

    //canvas.drawBitmap(bitmap_role, width/2-bitmap_role.getWidth()/2, y, null);

    canvas.drawBitmap(bitmap_role, x-bitmap_role.getWidth()/2, y-bitmap_role.getHeight()/2, null);

    }

    //重写父类中的 onTouchEvent就可以监听到 触摸事件了 记住要设置焦点喔

    @Override

    public boolean onTouchEvent(MotionEvent event) {

    gd.onTouchEvent(event); //通知手势识别方法

    return true;

    }

    public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {

    }

     

    public void surfaceCreated(SurfaceHolder surfaceHolder) {

    //获取屏幕的 宽高 只有在 surface创建的时候 才有效 ,才构造方法中获取 宽高是获取不到的

    width=this.getWidth();

    height=this.getHeight();

    //初始化绘图线程

    gameViewThread=new GameViewThread();

    gameViewThread.flag=true;

    gameViewThread.start();

    }

     

    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

    gameViewThread.flag=false; //销毁线程

    }

     

    class GameViewThread extends Thread{

    public boolean flag;

    public void run(){

    while(flag){

    Canvas canvas=null;

    try{

    canvas=surfaceHolder.lockCanvas(); //锁定画布 并获取canvas

    onDraw(canvas);//调用onDraw 渲染到屏幕

    surfaceHolder.unlockCanvasAndPost(canvas); //此步不要忘记了喔 否则界面上显示不出来的

    }catch(Exception e){

    e.printStackTrace();

    }

    try {

    Thread.sleep(10);//线程休眠时间 控制帧数

    } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } //每一秒刷新一次

    }

    }

    }

    //**************************下面是手势识别的重写方法*******************************************

    //屏幕点下

    public boolean onDown(MotionEvent arg0) {

    Log.d(TAG, "onDown");

    Toast.makeText(this.context, "你点击了屏幕", Toast.LENGTH_SHORT).show();

    return false;

    }

    //屏幕点下

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,

    float velocityY) {

    Log.d(TAG, "onFling");

    Toast.makeText(this.context, "你拖动屏幕后弹起", Toast.LENGTH_SHORT).show();

    return false;

    }

    //屏幕点下 并长按时触发

    public void onLongPress(MotionEvent e) {

    Log.d(TAG, "onLongPress");

    Toast.makeText(this.context, "你长按了屏幕", Toast.LENGTH_SHORT).show();

    }

    //屏幕拖动

    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,

    float distanceY) {

    this.x=this.x-distanceX;

    this.y=this.y-distanceY;

    Toast.makeText(this.context, "你拖动了屏幕", Toast.LENGTH_SHORT).show();

    return false;

    }

    //屏幕长按

    public void onShowPress(MotionEvent e) {

    // TODO Auto-generated method stub

    Toast.makeText(this.context, "你长按屏幕后弹起", Toast.LENGTH_SHORT).show();

    Log.d(TAG, "onShowPress");

    }

    //屏幕点击后弹起

    public boolean onSingleTapUp(MotionEvent e) {

    Log.d(TAG, "onSingleTapUp");

    Toast.makeText(this.context, "你弹起屏幕", Toast.LENGTH_SHORT).show();

    return false;

    }

    }

    另一个关于手势监听的详细例子:

    public class MyGesture extends Activity implements OnTouchListener, OnGestureListener {   

       private GestureDetector mGestureDetector;   

    public MyGesture() {   

            mGestureDetector = new GestureDetector(this);   

        }   

        public void onCreate(Bundle savedInstanceState) {   

            super.onCreate(savedInstanceState);   

            setContentView(R.layout.main);   

            TextView tv = (TextView) findViewById(R.id.tv);   

            tv.setOnTouchListener(this);   

            tv.setFocusable(true);   

            tv.setClickable(true);   

            tv.setLongClickable(true);   

            mGestureDetector.setIsLongpressEnabled(true);   

        }   

           

        /*  

         * 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector  

         * 来分析是否有合适的callback函数来处理用户的手势  

         */    

        public boolean onTouch(View v, MotionEvent event) {   

            return mGestureDetector.onTouchEvent(event);   

        }     

        // 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发   

       public boolean onDown(MotionEvent arg0) {   

            Log.i("MyGesture""onDown");   

            Toast.makeText(this"onDown", Toast.LENGTH_SHORT).show();   

            return true;       }     

       /*  

         * 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发      

         * 注意和onDown()的区别,强调的是没有松开或者拖动的状态  

         */  

        public void onShowPress(MotionEvent e) {   

            Log.i("MyGesture""onShowPress");   

            Toast.makeText(this"onShowPress", Toast.LENGTH_SHORT).show();   

        }   

        // 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发   

        public boolean onSingleTapUp(MotionEvent e) {   

            Log.i("MyGesture""onSingleTapUp");   

            Toast.makeText(this"onSingleTapUp", Toast.LENGTH_SHORT).show();   

            return true;   

        }          

    // 用户按下触摸屏、快速移动后松开,由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(this"onFling", Toast.LENGTH_LONG).show();   

            return true;   

        }          

        // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发   

        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {   

            Log.i("MyGesture""onScroll");   

            Toast.makeText(this"onScroll", Toast.LENGTH_LONG).show();   

            return true;   

        }   

        // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发   

        public void onLongPress(MotionEvent e) {   

            Log.i("MyGesture""onLongPress");   

            Toast.makeText(this"onLongPress", Toast.LENGTH_LONG).show();   

        }   

    }  

    public class MyGesture extends Activity implements OnTouchListener, OnGestureListener {
        private GestureDetector mGestureDetector;
        public MyGesture() {
         mGestureDetector = new GestureDetector(this);
        }
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            TextView tv = (TextView) findViewById(R.id.tv);
            tv.setOnTouchListener(this);
            tv.setFocusable(true);
            tv.setClickable(true);
            tv.setLongClickable(true);
            mGestureDetector.setIsLongpressEnabled(true);
        }
       
        /*
         * 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector
         * 来分析是否有合适的callback函数来处理用户的手势
         */
     public boolean onTouch(View v, MotionEvent event) {
      return mGestureDetector.onTouchEvent(event);
     }

     // 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发
     public boolean onDown(MotionEvent arg0) {
      Log.i("MyGesture", "onDown");
      Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show();
      return true;
     }
     
     /*
      * 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
      * 注意和onDown()的区别,强调的是没有松开或者拖动的状态
      */
     public void onShowPress(MotionEvent e) {
      Log.i("MyGesture", "onShowPress");
      Toast.makeText(this, "onShowPress", Toast.LENGTH_SHORT).show();
     }
     
     // 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
     public boolean onSingleTapUp(MotionEvent e) {
      Log.i("MyGesture", "onSingleTapUp");
      Toast.makeText(this, "onSingleTapUp", Toast.LENGTH_SHORT).show();
      return true;
     }
     
     // 用户按下触摸屏、快速移动后松开,由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(this, "onFling", Toast.LENGTH_LONG).show();
      return true;
     }
     
     // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
      Log.i("MyGesture", "onScroll");
      Toast.makeText(this, "onScroll", Toast.LENGTH_LONG).show();
      return true;
     }
     
     // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
     public void onLongPress(MotionEvent e) {
      Log.i("MyGesture", "onLongPress");
      Toast.makeText(this, "onLongPress", Toast.LENGTH_LONG).show();
     }
    }

    Fling事件的处理代码:除了第一个触发Fling的ACTION_DOWN和最后一个ACTION_MOVE中包含的坐标等信息外,我们还可以根据用户在X轴或者Y轴上的移动速度作为条件。比如下面的代码中我们就在用户移动超过100个像素,且X轴上每秒的移动速度大于200像素时才进行处理。

    1. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {   
    2.     // 参数解释:   
    3.     // e1:第1个ACTION_DOWN MotionEvent   
    4.     // e2:最后一个ACTION_MOVE MotionEvent   
    5.     // velocityX:X轴上的移动速度,像素/秒   
    6.     // velocityY:Y轴上的移动速度,像素/秒   
    7.   
    8.     // 触发条件 :   
    9.     // X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒   
    10.        
    11.     final int FLING_MIN_DISTANCE = 100, FLING_MIN_VELOCITY = 200;   
    12.     if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) {   
    13.         // Fling left   
    14.         Log.i("MyGesture""Fling left");   
    15.         Toast.makeText(this"Fling Left", Toast.LENGTH_SHORT).show();   
    16.     } else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) {   
    17.         // Fling right   
    18.         Log.i("MyGesture""Fling right");   
    19.         Toast.makeText(this"Fling Right", Toast.LENGTH_SHORT).show();   
    20.     }   
    21.     return false;   
    22. }  

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
     // 参数解释:
     // e1:第1个ACTION_DOWN MotionEvent
     // e2:最后一个ACTION_MOVE MotionEvent
     // velocityX:X轴上的移动速度,像素/秒
     // velocityY:Y轴上的移动速度,像素/秒

     // 触发条件 :
     // X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒
     
     final int FLING_MIN_DISTANCE = 100, FLING_MIN_VELOCITY = 200;
     if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) {
      // Fling left
      Log.i("MyGesture", "Fling left");
      Toast.makeText(this, "Fling Left", Toast.LENGTH_SHORT).show();
     } else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) {
      // Fling right
      Log.i("MyGesture", "Fling right");
      Toast.makeText(this, "Fling Right", Toast.LENGTH_SHORT).show();
     }
     return false;
    }

     这个例子中,tv.setLongClickable( true )是必须的,因为 只有这样,view才能够处理不同于Tap(轻触)的hold(即ACTION_MOVE,或者多个ACTION_DOWN),我们同样可以通过layout定义中的android:longClickable来做到这一点。

    SimpleOnGestureListener

    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. }  

    我们知道,一般的View只能响应点击(Click)和长按(LongPress)事件。这是因为View里只暴露了这些listener给我们使用。而实质上,View是在onTouchEvent(MotionEvent event)里对用户的动作做了一定的分析,从而通知我们是发生了点击还是长按等事件。

    View里提供的回调在我描述的场景里,并不能满足要求。因此,GestureDetector出场了。我需要对其啃透才能写出自己的ActionDetector

    GestureDetector类可以帮助我们分析用户的动作,和ViewonTouchEvent的处理方式差不多,但分析的动作类型更加细致,以下是它的回调接口:

    public interface OnGestureListener {

     

                    // Touch down时触发, edown时的MotionEvent

     

                    boolean onDown(MotionEvent e);

     

                    // Touch down之后一定时间(115ms)触发,edown时的MotionEvent

     

                    void onShowPress(MotionEvent e);

     

                    // Touch up时触发,eup时的MotionEvent

     

                    boolean onSingleTapUp(MotionEvent e);

     

                    // 滑动时触发,e1down时的MotionEvente2move时的MotionEvent

     

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

     

                    // Touch down之后一定时间(500ms)触发,edown时的MotionEvent

     

                    void onLongPress(MotionEvent e);

     

                    // 滑动一段距离,up时触发,e1down时的MotionEvente2up时的MotionEvent

     

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

     

    }

     

     

     

    public interface OnDoubleTapListener {

     

                    // 完成一次单击,并确定没有二击事件后触发(300ms),edown时的MotionEvent

     

                    boolean onSingleTapConfirmed(MotionEvent e);

     

                    // 第二次单击down时触发,e为第一次down时的MotionEvent

     

                    boolean onDoubleTap(MotionEvent e);

     

                    // 第二次单击down,moveup时都触发,e为不同时机下的MotionEvent

     

                    boolean onDoubleTapEvent(MotionEvent e);

     

    }

     

    其中GestureDetector.SimpleOnGestureListenerFramework帮我们简化了)是实现了上面提到的OnGestureListenerOnDoubleTapListener两个接口的类,我们只需要继承它并重写其中我们关心的回调即可。

     

    后,再提一下双击和三击的识别过程:在第一次单击down时,给Hanlder发送了一个延时300ms的消息,如果300ms里,发生了第二次单击的down事件,那么,就认为是双击事件了,并移除之前发送的延时消息。如果300ms后仍没有第二次的down消息,那么就判定为SingleTapConfirmed事件(当然,此时用户的手指应已完成第一次点击的up过程)。三击的判定和双击的判定类似,只是多了一次发送延时消息的过程.

     

    引用其他。

     

  • 相关阅读:
    VB Treeview控件 介绍与使用
    基于V4L2的视频驱动开发
    Jlinkv8 灯不亮重新烧写固件的办法
    使用JLink间接烧写S3C2410、S3C2440开发板Nor、Nand Flash的方法
    linux 开机自动执行脚本或者一些指定的程序
    FrameBuffer编程二(简单程序下)
    c语言内存分配函数
    FrameBuffer编程二(简单的程序上)
    FrameBuffer编程一(数据结构)
    mmap函数介绍
  • 原文地址:https://www.cnblogs.com/crazywenza/p/2799646.html
Copyright © 2020-2023  润新知