在View与用户的交互处理中,通常可以采用重写View的onTouchEvent方法来判断处理手势的一些操作,这种方式需要开发者自己处理手势的一些数据判断,在简单的手势例如上下左右滑动之类容易处理,遇到一些复杂的手势操作就很难判断处理。Android的View包中给我们提供了GestureDetector手势处理类来帮助开发者来处理复杂的手势操作事件。
GestureDetector
是在API LEVEL1级别所提供的类,在SDK Version 22中引入了GestureDetectorCompat兼容类,也就是GestureDetector增加了对低版本的兼容性,所以现在已废弃GestureDetector,转而使用新版本的GestureDetectorCompat类。
public final class GestureDetectorCompat
extends Objectjava.lang.Object
↳ android.support.v4.view.GestureDetectorCompat
GestureDetectorCompat类使用所提供的MotionEvents检测各种手势和事件。当一个特定的手势动作事件发生时,GestureDetector.OnGestureListener监听器回调会通知用户所发生的事件。这个类只能用于通过触摸屏幕所触发的MotionEvents事件。
框架的手势检测器的兼容性实现保证了在所有平台版本上,从Jellybean MR1版本骑更新的焦点滚动行为都可以运行。
GestureDetector类对外提供了两个接口::OnGestureListener,OnDoubleTapListener。
public interface OnGestureListener {
//按下
boolean onDown(MotionEvent e);
//按住
void onShowPress(MotionEvent e);
//抬起
boolean onSingleTapUp(MotionEvent e);
//滚动
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
//长按
void onLongPress(MotionEvent e);
//快速滑动
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
}
OnGestureListener 监听器接口中包含了6个方法,分别是:
public interface OnDoubleTapListener {
//确认单击
boolean onSingleTapConfirmed(MotionEvent e);
//双击
boolean onDoubleTap(MotionEvent e);
//双击
boolean onDoubleTapEvent(MotionEvent e);
}
当双击或确认单击时触发该事件监听器。
使用很简单,只需要在自定义View中或者Activity,Fragment中实现GestureDetector.OnGestureListener接口,然后创建一个GestureDetectorCompat 实例,参数中第一个参数为Context,第二个参数为OnGestureListener接口,然后重写自定义View或者Activity,Fragment的onTouchEvent方法,在onTouchEvent方法中调用gestureDetector.onTouchEvent(event);来将触摸事件分发给GestureDetector手势监听器处理。
public class MainActivity extends BaseActivity implements GestureDetector.OnGestureListener{
private static final String DEBUG_TAG="Gestures";
private GestureDetectorCompat gestureDetector;
@Override
protected void initView() {
setContentView(R.layout.activity_main);
}
@Override
protected void initData() {
gestureDetector=new GestureDetectorCompat(this,this);
}
@Override
protected void initListener() {
}
@Override
public boolean onTouchEvent(MotionEvent event){
return gestureDetector.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent e) {
Log.d(DEBUG_TAG,"onDown:"+e.toString());
return false;
}
@Override
public void onShowPress(MotionEvent e) {
Log.d(DEBUG_TAG,"onShowPress:"+e.toString());
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
Log.d(DEBUG_TAG,"onSingleTapUp:"+e.toString());
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.d(DEBUG_TAG,"onScroll:"+e1.toString()+"--"+e2.toString()+"--"+distanceX+"--"+distanceY);
return false;
}
@Override
public void onLongPress(MotionEvent e) {
Log.d(DEBUG_TAG,"onLongPress:"+e.toString());
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.d(DEBUG_TAG,"onFling:"+e1.toString()+"=="+e2.toString()+"=="+velocityX+"=="+velocityY);
return false;
}
}
同时也可以在View的onTouchListener方法中处理作用在View上的手势:
public class MainActivity extends BaseActivity {
private static final String DEBUG_TAG="Gestures";
private GestureDetectorCompat gestureDetector;
private LinearLayout container;
@Override
protected void initView() {
setContentView(R.layout.activity_main);
container= (LinearLayout) findViewById(R.id.Container);
}
@Override
protected void initData() {
gestureDetector=new GestureDetectorCompat(this,new MyGestureListener());
}
@Override
protected void initListener() {
container.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);
return false;
}
});
}
private class MyGestureListener extends GestureDetector.SimpleOnGestureListener{
private static final String DEBUG_TAG="Gestures";
@Override
public boolean onDown(MotionEvent e) {
Log.d(DEBUG_TAG,"onDown:"+e.toString());
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.d(DEBUG_TAG,"onFling:"+e1.toString()+"=="+e2.toString()+"=="+velocityX+"=="+velocityY);
return false;
}
}
}
public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener,
OnContextClickListener {
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
public void onLongPress(MotionEvent e) {
}
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return false;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
public void onShowPress(MotionEvent e) {
}
public boolean onDown(MotionEvent e) {
return false;
}
public boolean onDoubleTap(MotionEvent e) {
return false;
}
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
public boolean onSingleTapConfirmed(MotionEvent e) {
return false;
}
public boolean onContextClick(MotionEvent e) {
return false;
}
}
SimpleOnGestureListener 是GestureDetector手势检测器里面的一个轻量级的静态内部类,实现了OnGestureListener, OnDoubleTapListener,OnContextClickListener所有接口方法,但全是空方法和返回false。这个静态内部类主要是方便开发者实现自己需要的监听器方法,当自己实现OnGestureListener接口时,需要实现全部6个监听器方法,其他很多时候并不是要处理所有的手势操作,但只需要处理其中的某几个手势监听方法时,可以继承SimpleOnGestureListener 实现一个子类,重写里面的某几个手势监听方法就可以达到相同的目的。
如下代码只实现了onDown和onFling方法:
public class MainActivity extends BaseActivity{
private static final String DEBUG_TAG="Gestures";
private GestureDetectorCompat gestureDetector;
@Override
protected void initView() {
setContentView(R.layout.activity_main);
}
@Override
protected void initData() {
gestureDetector=new GestureDetectorCompat(this,new MyGestureListener());
}
@Override
protected void initListener() {
}
@Override
public boolean onTouchEvent(MotionEvent event){
return gestureDetector.onTouchEvent(event);
}
private class MyGestureListener extends GestureDetector.SimpleOnGestureListener{
private static final String DEBUG_TAG="Gestures";
@Override
public boolean onDown(MotionEvent e) {
Log.d(DEBUG_TAG,"onDown:"+e.toString());
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.d(DEBUG_TAG,"onFling:"+e1.toString()+"=="+e2.toString()+"=="+velocityX+"=="+velocityY);
return false;
}
}
}