Android中手势识别GestureDetector分析

在Android系统中,每一次手势交互都会依照以下顺序执行。

1. 接触接触屏一刹那,触发一个MotionEvent事件。 

2. 该事件被OnTouchListener监听,在其onTouch()方法里获得该MotionEvent对象。 

3. 通过GestureDetector(手势识别器)转发次MotionEvent对象


MotionEvent: 这个类用于封装手势、触摸笔、轨迹球等等的动作事件。其内部封装了两个重要的属性X和Y,这两个属性分别用于记录横轴和纵轴的坐标。
GestureDetector: 识别各种手势,它提供了OnGestureListener和OnDoubleTapListener两个接口,以及一个内部类SimpleOnGestureListener。
手势交互的监听接口,其中提供了多个抽象方法,并根据GestureDetector的手势识别结果调用相对应的方法。

代码说明:

布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/a" />

</RelativeLayout>

实现OnGestureListener接口:

package com.example.gesturedetectortest;

import android.os.Bundle;
import android.util.Log;
import android.app.Activity;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
// OnGestureListener: 这是一个手势交互的监听接口,
//其中提供了多个抽象方法,并根据GestureDetector的手势识别结果调用相对应的方法。
public class MainActivity extends Activity  implements OnGestureListener,OnTouchListener{
	public static final String TAG=MainActivity.class.getSimpleName();
	private ImageView iv;
	private GestureDetector detector;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		iv=(ImageView)findViewById(R.id.iv);
		detector=new GestureDetector(this, this);
		iv.setOnTouchListener(this);
	}

	//在onTouchEvent()方法中,我们调用GestureDetector的onTouchEvent()方法,
	//将捕捉到的MotionEvent交给GestureDetector来分析是否有合适的callback函数来处理用户的手势  
	//	@Override
	//	public boolean onTouchEvent(MotionEvent event) {
	//		// TODO Auto-generated method stub
	//		return this.detector.onTouchEvent(event);
	//	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		// TODO Auto-generated method stub
		return this.detector.onTouchEvent(event);
	}
	//刚刚手指接触到触摸屏的那一刹那,由1个MotionEvent ACTION_DOWN触发 
	@Override
	public boolean onDown(MotionEvent e) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onDown   y=" + e.getY());  	
		return true;
	}
	// 手指按在触摸屏上,它的时间范围在按下起效,在长按之前,
	//由一个1个MotionEvent ACTION_DOWN触发  
	//注意和onDown()的区别,强调的是没有松开或者拖动的状态  
	@Override
	public void onShowPress(MotionEvent e) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onShowPress");
	}
	//手指离开触摸屏的那一刹那
	//由一个1个MotionEvent ACTION_UP触发  
	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onSingleTapUp    y=" + e.getY());
		return true;
	}
	//手指按下且在屏上滑动
	//由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onScroll:distanceX = " + distanceX + " distanceY = " + distanceY);
		return true;
	}
	//手指长按触屏幕,并且没有松开
	//由多个MotionEvent ACTION_DOWN触发
	@Override
	public void onLongPress(MotionEvent e) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onLongPress");
	}
	//手指在触摸屏上迅速移动,并松开的动作
	//由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发 
	//e1:第1个ACTION_DOWN MotionEvent ,e2:最后一个ACTION_MOVE MotionEven
	//velocityX:X轴上的移动速度,像素/秒  ,velocityY:Y轴上的移动速度,像素/秒   

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onFling");
		if(e1.getX()-e2.getX()>100&&Math.abs(velocityX)>200){
			Log.i(TAG, "onFling   向左滑动");
			return true;
		}else if(e1.getX()-e2.getX()<-100&&Math.abs(velocityX)>200){
			Log.i(TAG, "onFling   向右滑动");
			return true;
		}else if(e1.getY()-e2.getY()>10&&Math.abs(velocityY)>50){
			Log.i(TAG, "onFling   向上滑动  上位移="+(e1.getY()-e2.getY()));
			return true;
		}else if(e1.getY()-e2.getY()<-10&&Math.abs(velocityY)>50){
			Log.i(TAG, "onFling   向下滑动    下位移"+(e1.getY()-e2.getY()));
			return true;
		}
		return false;
	}


	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
}

onFling方法中可以通过其参数进行一些条件设置,如左右上下滑动的条件。

Activity中的onTouchEvent方法和OnTouchListener中的onTouch方法,都可以实现调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector来分析是否有合适的callback函数来处理用户的手势,两个直接的区别:查看http://www.xuebuyuan.com/1588148.html。

执行不同手势时,logcat显示:

Android中手势识别GestureDetector分析_第1张图片

SimpleOnGestureListener是一个抽象类,需要继承,可选择性的继承自己所需的方法。

下面这个测试,来自网络,其实和OnGestureListener比较多了几个方法。

package com.example.gesturedetectortest;

import android.app.Activity;
import android.os.Bundle;
import android.os.storage.OnObbStateChangeListener;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class SimpleOnGestureActivity extends Activity implements OnTouchListener{
	public static final String TAG=SimpleOnGestureActivity.class.getSimpleName();
	private GestureDetector detector;
	private ImageView iv;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_gestrue);
		iv=(ImageView)findViewById(R.id.iv);
		detector=new GestureDetector(this, new MySimpleGesture());
		iv.setOnTouchListener(this);
	}
	@Override
	public boolean onTouch(View v, MotionEvent event) {
		// TODO Auto-generated method stub
		return this.detector.onTouchEvent(event);

	}
	private class MySimpleGesture extends SimpleOnGestureListener{
		// 双击的第二下Touch down时触发    
		public boolean onDoubleTap(MotionEvent e) {   
			Log.i(TAG, "onDoubleTap");   
			return super.onDoubleTap(e);   
		}   

		// 双击的第二下Touch down和up都会触发,可用e.getAction()区分   
		public boolean onDoubleTapEvent(MotionEvent e) {   
			Log.i(TAG, "onDoubleTapEvent");   
			return super.onDoubleTapEvent(e);   
		}   

		// Touch down时触发    
		public boolean onDown(MotionEvent e) {   
			Log.i(TAG, "onDown");   
			return super.onDown(e);   
		}   

		// Touch了滑动一点距离后,up时触发   
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {   
			Log.i(TAG, "onFling");   
			return super.onFling(e1, e2, velocityX, velocityY);   
		}   

		// Touch了不移动一直Touch down时触发   
		public void onLongPress(MotionEvent e) {   
			Log.i(TAG, "onLongPress");   
			super.onLongPress(e);   
		}   

		// Touch了滑动时触发   
		public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {   
			Log.i(TAG, "onScroll");   
			return super.onScroll(e1, e2, distanceX, distanceY);   
		}   

		/*  
		 * Touch了还没有滑动时触发  
		 * (1)onDown只要Touch Down一定立刻触发  
		 * (2)Touch Down后过一会没有滑动先触发onShowPress再触发onLongPress  
		 * So: Touch Down后一直不滑动,onDown -> onShowPress -> onLongPress这个顺序触发。  
		 */  
		public void onShowPress(MotionEvent e) {   
			Log.i(TAG, "onShowPress");   
			super.onShowPress(e);   
		}   
		/*  
		 * 两个函数都是在Touch Down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touch Up时触发  
		 * 点击一下非常快的(不滑动)Touch Up: onDown->onSingleTapUp->onSingleTapConfirmed  
		 * 点击一下稍微慢点的(不滑动)Touch Up: onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed   
		 */    
		public boolean onSingleTapConfirmed(MotionEvent e) {   
			Log.i(TAG, "onSingleTapConfirmed");   
			return super.onSingleTapConfirmed(e);   
		}   
		public boolean onSingleTapUp(MotionEvent e) {   
			Log.i(TAG, "onSingleTapUp");   
			return super.onSingleTapUp(e);   
		}   

	}
}


一些关于手势的优秀的开源框架:http://jcodecraeer.com/plus/list.php?tid=31&codecategory=16500

示例代码下载


你可能感兴趣的:(android,手势识别,gesturedetector)