屏幕触摸OnFling(),OnScroll(),OnDrag()

对于一个view, 常用的操作有点击(click)和长按(long press)二种。实际上,这些操作类型是Android内部在onTouchEvent(MotionEvent event)里对用户的动作做了一定的分析,从而通知应用程序是发生了点击还是长按等事件。

借助GestureDetector来分析出更细致的操作类型。基本的过程就是创建一个myGestureDetector对象,传入自己定义的myOnGestureListener对象,在自己的onTouchEvent回调函数中将接收到的event传给myGestureDetector进行分析,myOnGestureListener会回调我们定义的动作。

从 GestureDetector.SimpleOnGestureListener派生出myListener 会更简单,因为这个类已经实现了全部接口,只是没有什么实际有用的功能。


public MainActivity extends Activity{
    private GestureDetector mGestureDetector;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); 
        mGestureDetector = new GestureDetector(this, new MyGestureListener());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }

    class MyGestureListener extends GestureDetector.OnGestureListener{ //共有6个方法:

        // 用户轻触触屏:Touch down(仅一次)时触发, e为down时的MotionEvent:
        public boolean onDown(MotionEvent e){
            return true;
        }

        // 用户轻触触屏,且尚未松开或拖动:
        //   在Touch down(仅一次)之后一定时间(115ms)触发,e为down时的MotionEvent:
        public boolean onShowPress(MotionEvent e){
            return true;
        }

        // 用户(轻触触屏后)松开:Touch up(仅一次)时触发,e为up时的MotionEvent:
        public boolean onSingleTapUp(MotionEvent e){
            return true;
        }

        // 用户轻触触屏,并拖动:
        //   按下并滑动时触发,e1为down(仅一次)时的MotionEvent,e2为move(多个)时的MotionEvent:
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){
            return true;
        }

        // 用户长按触屏(此View必须是可长按的: myView->setLongClickable(true);):
        //   在Touch down之后一定时间(500ms)后,由多个down事件触发,e为down时的MotionEvent:
        public boolean onLongPress(MotionEvent e){
            return true;
        }

        // 用户按下触屏、快速移动后松开:
        //   按下并快速滑动一小段距离(多个move),up时触发,e1为down(仅一次)时的MotionEvent,
        //   e2为up(仅一次)时的MotionEvent:
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){
            return true;
        }
    }
}


至于doubletap的检测,可以通过设置mGestureDetector的OnDoubleTapListener来实现:


GestureDetector.OnDoubleTapListener doubleTapListener = new GestureDetector.OnDoubleTapListener() {

    // 完成一次单击,并确定(300ms内)没有发生第二次单击事件后触发,e为down时的MotionEvent:
    public boolean onSingleTapConfirmed(MotionEvent e){
        return true;
    }

    // 第二次单击down时触发,e为第一次down时的MotionEvent:
    public boolean onDoubleTap(MotionEvent e){
        return true;
    }

    // 第二次单击down、move和up时都触发,e为不同时机下的MotionEvent:
    public boolean onDoubleTapEvent(MotionEvent e){
        return true;
    }
}
mGestureDetector.setDoubleTapListener(doubleTapListener);    


具体地说,典型的触屏事件及其listener执行的流程见下:


  • 1.单击事件的执行流程:

有两种情况,一种是时间很短,一种时间稍长。

时间很短:onDown —-> onSingleTapUp —-> onSingleTapConfirmed

时间稍长:onDown —-> onShowPress —-> onSingleTapUp —-> onSingleTapConfirmed

  • 2.长按事件

onDown —-> onShowPress —-> onLongPress

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

onDown —-> onScroll —-> onScroll —-> onScroll —-> ……… —-> onFling

  • 4.拖动(drag)

onDown —-> onScroll —-> onScroll —-> onFiling

注意:有的时候会触发onFiling,但是有的时候不会触发,z这是因为人的动作不标准所致。

I Don't Want Your Money, I Want Aragaki Yui.