Android GestureDetector 总结

来源:互联网 发布:淘宝会员无线端装修 编辑:程序博客网 时间:2024/05/22 03:42
  1. GestureDetector & OnTouchListener 区别
    OnTouchListener 实现了如触摸屏相关的事件
    OnGestureListener实现了 手势相关的事件

首先看OnTouchListener
Class 结构:
这里写图片描述

我们可以看出里面的概要方法有一个onTouch 方法这个方法就是我们需要实现的一个方法,
Called when a touch event is dispatched to a view.
一个触摸事件调用时被分配到一个视图中。从而实现对触摸时间的监听

例子:

public class Main3 extends Activity implements View.OnTouchListener{    private ImageView image;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        image = (ImageView) findViewById(R.id.image);        //监听这个ImageView组件上的触摸屏时间        image.setOnTouchListener(this);    }    @Override    public boolean onTouch(View v, MotionEvent event) {  switch (event.getAction()){      case MotionEvent.ACTION_UP:          Log.e("ACTION_UP","Touch" +event.getAction());          break;      case MotionEvent.ACTION_DOWN:          Log.e("ACTION_DOWN","Touch" +event.getAction());          break;      case MotionEvent.ACTION_MOVE:          Log.e("ACTION_MOVE","Touch" +event.getAction());          break;  }       return true;    }    }

我们可以通过MotionEvent的getAction()方法来获取Touch事件的类型,包括 ACTION_DOWN(按下触摸屏), ACTION_MOVE(按下触摸屏后移动受力点), ACTION_UP(松开触摸屏)和ACTION_CANCEL(不会由用户直接触发)。借助对于用户不同操作的判断,结合getRawX()、 getRawY()、getX()和getY()等方法来获取坐标后,我们可以实现诸如拖动某一个按钮,拖动滚动条等功能。
可以看到OnTouchListener只能监听到三种触摸事件,即按下,移动,松开,如果想要监听到双击、滑动、长按等复杂的手势操作,这个时候就必须得用到OnGestureListener了。
接下来是OnGestureListener
结构图:
这里写图片描述
OnGestureListener 里面的方法
onDown // 用户轻触触摸屏
OnFling // 用户快速抛掷
OnLongPress // 用户长按触摸屏
OnScroll // 用户按下触摸屏,并拖动
OnShowPrees // 用户轻触触摸屏,尚未松开或拖动
OnSingleTapup // 用户(轻触触摸屏后)松开

这里有疑问了,我们ontouch 是通过设置他的监听事件来运行的,可是Gesture 里面并没有找到这个设置事件呢?还是可以在文档中找到的
这里写图片描述

文档中说是需要在Ontouch的监听 里面 调用 他的 onTouchEvent 事件这样就可以监听手势了
例子:

public class Main3 extends Activity implements View.OnTouchListener, GestureDetector.OnGestureListener {    private ImageView image;    private GestureDetector mGestureDetector;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        image = (ImageView) findViewById(R.id.image);        //监听这个ImageView组件上的触摸屏时间        image.setOnTouchListener(this);        //        mGestureDetector = new GestureDetector(this);        //        // GestureDetector的构造函数在4.1版本中已经过时,可以使用推荐的:        // 注意前一个this代表的是一个Context,后一个this代表的是一个OnGestureListener。        // Activity继承自Context, 而你的activity应该实现了(implements)OnGestureListener接口。        mGestureDetector = new GestureDetector(this, this);    }    @Override    public boolean onTouch(View v, MotionEvent event) {//  switch (event.getAction()){//      case MotionEvent.ACTION_UP://          Log.e("ACTION_UP","Touch" +event.getAction());//          break;//      case MotionEvent.ACTION_DOWN://          Log.e("ACTION_DOWN","Touch" +event.getAction());//          break;//      case MotionEvent.ACTION_MOVE://          Log.e("ACTION_MOVE","Touch" +event.getAction());//          break;////  }////        return true;        return mGestureDetector.onTouchEvent(event);    }    // 用户轻触触摸屏    @Override    public boolean onDown(MotionEvent e) {        Log.e("MyGesture", "onDown");        return true;    }    // 用户轻触触摸屏,尚未松开或拖动    @Override    public void onShowPress(MotionEvent e) {        Log.e("MyGesture", "onShowPress");    }    // 用户(轻触触摸屏后)松开,    @Override    public boolean onSingleTapUp(MotionEvent e) {        Log.e("MyGesture", "onSingleTapUp");        return true;    }    //    用户按下触摸屏,并拖动    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        Log.e("MyGesture", "onScroll");        return true;    }    // 用户长按触摸屏    @Override    public void onLongPress(MotionEvent e) {        Log.e("MyGesture", "onLongPress");    }    @Override    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {        Log.e("MyGesture", "onFling");        return true;    }}

下面是几个方法的调用顺序:
长按

10-16 16:05:45.319 10496-10496/? E/MyGesture﹕ onDown
10-16 16:05:45.489 10496-10496/? E/MyGesture﹕ onShowPress
10-16 16:05:45.999 10496-10496/? E/MyGesture﹕ onLongPress

轻触

10-16 16:06:10.479 10496-10496/? E/MyGesture﹕ onDown
10-16 16:06:10.549 10496-10496/? E/MyGesture﹕ onSingleTapUp

拖动

10-16 16:06:35.709 10496-10496/? E/MyGesture﹕ onDown
10-16 16:06:36.469 10496-10496/? E/MyGesture﹕ onScroll
10-16 16:06:36.489 10496-10496/? E/MyGesture﹕ onScroll
10-16 16:06:36.499 10496-10496/? E/MyGesture﹕ onScroll

抛掷

10-16 16:07:15.249 10496-10496/? E/MyGesture﹕ onDown
10-16 16:07:15.359 10496-10496/? E/MyGesture﹕ onScroll
10-16 16:07:15.379 10496-10496/? E/MyGesture﹕ onScroll
10-16 16:07:15.389 10496-10496/? E/MyGesture﹕ onScroll
10-16 16:07:15.409 10496-10496/? E/MyGesture﹕ onScroll
10-16 16:07:15.419 10496-10496/? E/MyGesture﹕ onFling

这里写图片描述

(1)MotionEvent中 e1是手指第一次按上屏幕的起点,e2是抬起手指离开屏幕的终点,根据上图Android屏幕坐标系可知:

手指向右滑动,终点(e2)在起点(e1)的右侧,有e2.getX() - e1.getX() 大于0 手指向左滑动,终点(e2)在起点(e1)的左侧,有e2.getX() - e1.getX() 小于0 手指向下滑动,终点(e2)在起点(e1)的下侧,有e2.getY() - e1.getY() 大于0 手指向上滑动,终点(e2)在起点(e1)的上侧,有e2.getY() - e1.getY() 小于0

(2)onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)

distanceX,是前后两次call的X距离,不是e2与e1的水平距离 distanceX,是前后两次call的Y距离,不是e2与e1的垂直距离 具体数值的方向,请详见上图(中)

(3)onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

velocityX,是X轴的每秒速度 velocityY,是Y轴的每秒速度 具体数值的方向,请详见上图(右) 仔细观察可以发现:velocityX、velocityY的方向与distanceX、distanceY方向正好相反

  1. GestureDetector 内容方法
    下面是GestureDetector 的具体使用方法,使用抛掷做的一个切换界面的demo,判断了四个方向的手势。
public class MainActivity extends Activity implements View.OnTouchListener, GestureDetector.OnGestureListener {    //创建一个用于识别手势 的GestureDetecttor 对象    private GestureDetector detector = new GestureDetector(this);    //定义一个数组,用于放漂亮的女孩    int[] girls = new int[]{R.drawable.girl1, R.drawable.girl2, R.drawable.girl3};    //定义数组下标,以方便观看各个女孩    private int index;    private ImageView image;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        image = (ImageView) findViewById(R.id.image);        //设置一个初始显示的girl吧        image.setImageResource(girls[index]);        //监听这个ImageView组件上的触摸屏时间        image.setOnTouchListener(this);        //下面两个要记得设哦,不然就没法处理轻触以外的事件了,例如抛掷动作。        image.setLongClickable(true);        detector.setIsLongpressEnabled(true);    }    //用于呼喊下一个女孩的方法    public void goNext() {        index++;        index = Math.abs(index % girls.length);        image.setImageResource(girls[index]);    }    //用户呼唤上一个女孩的方法    public void goPrevious() {        index--;        index = Math.abs(index % girls.length);        image.setImageResource(girls[index]);    }    //此方法在触摸屏被触摸,即发生触摸事件(接触和抚摸两个事件,挺形象)的时候被调用。    @Override    public boolean onTouch(View v, MotionEvent event) {        detector.onTouchEvent(event);        return true;    }    //在抬起时被调用    @Override    public boolean onSingleTapUp(MotionEvent e) {        return false;    }    //在按住时被调用    @Override    public void onShowPress(MotionEvent e) {    }    //在滚动时调用    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        return false;    }    //在长按时被调用    @Override    public void onLongPress(MotionEvent e) {    }//    在抛掷动作时被调用//    @Override//    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {////        //velocityX表示横向的移动,根据手指移动的方向切换女孩//        Log.e("x",velocityX+"");//        Log.e("y",velocityY+"");////        if (velocityX <  300) {//            goNext();//        } else if (velocityX > 300) {//            goPrevious();//        }//        return false;//    }    private  DisplayMetrics getscreen(){        DisplayMetrics dm = new DisplayMetrics();        this.getWindowManager().getDefaultDisplay().getMetrics(dm);        return dm;    }    @Override    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {        //这个可以判断 上下左右的四个手势动作        float x = e2.getX() - e1.getX();        float y = e2.getY() - e1.getY();        // 限制必须得划过屏幕的1/4才能算划过        float x_limit = getscreen().widthPixels / 4;        float y_limit = getscreen().heightPixels / 4;        float x_abs = Math.abs(x);        float y_abs = Math.abs(y);        if (x_abs >= y_abs) {            // gesture left or right            if (x > x_limit || x < -x_limit) {                if (x > 0) {                    // right                    Log.e("Tag", "right");                    startActivity(new Intent(this,Main2.class));                } else if (x <= 0) {                    // left                    startActivity(new Intent(this,Main3.class));                    Log.e("Tag", "left");                }            }        } else {            // gesture down or up            if (y > y_limit || y < -y_limit) {                if (y > 0) {                    // down                    Log.e("Tag", "down");                } else if (y <= 0) {                    // up                    Log.e("Tag", "up");                }            }        }        Log.e("Tag", "判断结束");        return true;    }    //在按下动作时被调用    @Override    public boolean onDown(MotionEvent e) {        return false;    }}
  1. GestureDetector 中SimpleOnScaleGestureListener&SimpleOnGestureListener 用法
    这里写图片描述

    If you only want to listen for a subset it might be easier to extend GestureDetector.SimpleOnGestureListener.
    官方推荐一个更简易,更建议使用的一个已实现的方法
    适用于单一手势
    下面是例子:

public class Main2 extends Activity implements View.OnTouchListener {    private GestureDetector gestureDetector; //手势探测器    private ScaleGestureDetector ScaleGesture;//比率手势探测器    private ImageView image;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        image = (ImageView) findViewById(R.id.image);        //监听这个ImageView组件上的触摸屏时间        image.setOnTouchListener(this);        gestureDetector = new GestureDetector(this, new DefGesture());        ScaleGesture = new ScaleGestureDetector(this,new ScaleGesture());    }    @Override    public boolean onTouch(View v, MotionEvent event) {        gestureDetector.onTouchEvent(event);        ScaleGesture.onTouchEvent(event);        return true; //true 代表可以分发  false  不可以分发    }}class DefGesture extends GestureDetector.SimpleOnGestureListener {    @Override    public boolean onDoubleTap(MotionEvent e) {        Log.e("onDoubleTap", e.getAction() + "");        return super.onDoubleTap(e);    }    @Override    public boolean onDoubleTapEvent(MotionEvent e) {        Log.e("onDoubleTapEvent", e.getAction() + "");        return super.onDoubleTapEvent(e);    }}//SimpleOnScaleGestureListener implements OnScaleGestureListenerclass ScaleGesture extends ScaleGestureDetector.SimpleOnScaleGestureListener {//双手指操作    @Override    public boolean onScale(ScaleGestureDetector detector) {        detector.getCurrentSpan();//两点间的距离跨度        detector.getCurrentSpanX();//两点间的x距离        detector.getCurrentSpanY();//两点间的y距离        detector.getFocusX();       //        detector.getFocusY();       //        detector.getPreviousSpan(); //上次        detector.getPreviousSpanX();//上次        detector.getPreviousSpanY();//上次        detector.getEventTime();    //当前事件的事件        detector.getTimeDelta();    //两次事件间的时间差        detector.getScaleFactor();  //与上次事件相比,得到的比例因子        Log.e("getCurrentSpan",    detector.getCurrentSpan() + "");        return true;    }}

代码下载地址:http://download.csdn.net/detail/v7428477/9187225

0 0
原创粉丝点击