原文地址:http://mypyg.iteye.com/blog/761331
手势即手触摸屏幕做出动作。
View可以通过onTouchEvent收到触摸屏幕事件,
我们可以通过View.setOnTouchListener()设置事件监听器
或者override onTouchEvent()来拦截这些事件,
在拦截函数中判断触摸点的轨迹及运动速度就可以判断出是什么手势。
Android系统提供了GestureDetector来方便手势的判断,即:在拦截函数中每次touchevent都把事件作为参数调用GestureDetector.onTouchEvent(),当有手势被识别出后,就会通知调用者。
为了能通知到调用者,GestureDetector在构造时要求传入一个实现了OnGestureListener接口的对象,
通过此对象就可以接收到各种手势通知了。
首先先用textview来实验:
用一个ViewFlipper放置两个Textview,当手指在屏幕上左右移动时进行进行切换。
由于textview本身不会处理touchevent,而是会将其继续上传,所以textview布局时layout_width及layout_height没有影响。
如果touch事件发生在textview上会继续上传到viewflipper;如果发生在viewflipper上那么就直接处理。
所以我们应该拦截发生在ViewFlipper上的touchEvent,并进行处理。
代码如下,在onCreate中完成界面布局及事件拦截函数设置:
- //创建一个ViewFlipper
- mVf = new ViewFlipper(this);
- //ViewFlipper打开长点击支持。如果不打开,无法收到长时间点击,那么手势判断就无从进行。
- mVf.setLongClickable(true);
- //拦截ViewFlipper的touch事件,并使用GestureDetector.onTouchEvent来处理
- mVf.setOnTouchListener(new OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- return mVfDetector.onTouchEvent(event);
- }
- });
- //添加一个textview。textview不能setLongClickable(true),
- //如果设置了那么发生在textview上的touch事件就无法传给viewflipper,
- //无法被手势识别对象处理了。
- TextView tv = new TextView(this);
- tv.setText("TextView 1");
- tv.setBackgroundColor(0xffffffff); //设置一个白色背景,方便看到textview区域
- mVf.addView(tv,new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
- //再添加一个textview
- TextView tv2 = new TextView(this);
- tv2.setText("TextView 2");
- tv2.setBackgroundColor(0xffffffff);
- mVf.addView(tv2,new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- //将viewFlipper作为Activity的主view显示
- setContentView(mVf);
//创建一个ViewFlipper
mVf = new ViewFlipper(this);
//ViewFlipper打开长点击支持。如果不打开,无法收到长时间点击,那么手势判断就无从进行。
mVf.setLongClickable(true);
//拦截ViewFlipper的touch事件,并使用GestureDetector.onTouchEvent来处理
mVf.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mVfDetector.onTouchEvent(event);
}
});
//添加一个textview。textview不能setLongClickable(true),
//如果设置了那么发生在textview上的touch事件就无法传给viewflipper,
//无法被手势识别对象处理了。
TextView tv = new TextView(this);
tv.setText("TextView 1");
tv.setBackgroundColor(0xffffffff); //设置一个白色背景,方便看到textview区域
mVf.addView(tv,new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
//再添加一个textview
TextView tv2 = new TextView(this);
tv2.setText("TextView 2");
tv2.setBackgroundColor(0xffffffff);
mVf.addView(tv2,new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
//将viewFlipper作为Activity的主view显示
setContentView(mVf);
在监听器中用到了GestureDetector对象,其是一个类成员对象,用如下代码创建:
- private GestureDetector mVfDetector = new GestureDetector(new OnGestureListener() {
- //手指在屏幕上移动距离小于此值不会被认为是手势
- private static final int SWIPE_MIN_DISTANCE = 120;
- //手指在屏幕上移动速度小于此值不会被认为手势
- private static final int SWIPE_THRESHOLD_VELOCITY = 200;
- //手势识别函数,到此函数被系统回调时说明系统认为发生了手势事件,
- //我们可以做进一步判定。
- @Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- //如果第1个坐标点大于第二个坐标点,说明是向左滑动
- //滑动距离以及滑动速度是额外判断,可根据实际情况修改。
- if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE &&
- Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
- //left
- Log.i("GestureDemo", "ViewFlipper left");
- mVf.showNext();
- return true;
- }else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE &&
- Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
- //right
- Log.i("GestureDemo", "ViewFlipper right");
- mVf.showPrevious();
- return true;
- }
- return false;
- }
- ... ...
- ... ...
- });
- }
源码: