当用户触摸屏幕的时候,会产生很多手势,例如down,up,scroll,filling等。
View类有一个内部接口——View.OnTouchListener,通过重写这个内部类的onTouch(View v,MotionEvent event)方法,可以处理一些简单的touch事件。但是如果需要处理一些复杂的手势,用这个接口会很麻烦。
Android sdk提供给我们了一个手势(Gesture)识别(Detector)类,通过这个类我们可以识别很多手势,主要是通过它的onTouchEvent(event)方法完成了不同手势的识别。
这个类对外提供了两个接口:OnGestureListener,OnDoubleTapListener,还有一个内部类SimpleOnGestureListener。SimpleOnGestureListener类是GestureDetector提供给我们的一个更方便的、经过简化的响应不同手势的类,这个类实现了上述两个类的接口(但是所有的方法都是空的),该类是static class,也就是说它实际上是一个外部类。我们可以在外部继承这个类,重写里面的手势处理方法。
启动手势识别类的方法:
GestureDetector mGestureDetector = new GestureDetector(new FlingGestureDector());
其中FlingGestureDetector()为重写的手势识别类
手势识别类FlingGestureDetector()的定义:
private class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener {
// 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发
//Touch down时触发,不论是touch (包括long) ,scroll
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
System.out.println("onDown");
return false;
}
/*
* 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
* 注意和onDown()的区别,强调的是没有松开或者拖动的状态 (单击没有松开或者移动时候就触发此事件,再触发onLongPress事件)
*/
//Touch了还没有滑动时触发
//(与onDown,onLongPress比较
//onDown只要Touch down一定立刻触发。
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
System.out.println("onShowPress");
}
// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
System.out.println("onSingleTopUp");
return false;
}
// 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
System.out.println("onScroll");
// TODO Auto-generated method stub
return false;
}
// 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
//Touch了不移动一直Touch down时触发
//Touchdown后过一会没有滑动先触发onShowPress再是onLongPress。
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
System.out.println("onLongPress");
}
/*
* 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE,
* 1个ACTION_UP触发(non-Javadoc)
* Fling事件的处理代码:除了第一个触发Fling的ACTION_DOWN和最后一个ACTION_MOVE中包含的坐标等信息外
* ,我们还可以根据用户在X轴或者Y轴上的移动速度作为条件
* 比如下面的代码中我们就在用户移动超过100个像素,且X轴上每秒的移动速度大于200像素时才进行处理。
*
* @see Android.view.GestureDetector.OnGestureListener#onFling(android.view.
* MotionEvent, Android.view.MotionEvent, float, float)
* 这个例子中,tv.setLongClickable( true )是必须的,因为
* 只有这样,view才能够处理不同于Tap(轻触)的hold(即ACTION_MOVE,或者多个ACTION_DOWN)
* ,我们同样可以通过layout定义中的Android:longClickable来做到这一点
*/
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
System.out.println("onFling");
// 参数解释:
// e1:第1个ACTION_DOWN MotionEvent
// e2:最后一个ACTION_MOVE MotionEvent
// velocityX:X轴上的移动速度,像素/秒
// velocityY:Y轴上的移动速度,像素/秒
// 触发条件 :
// X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒
final int FLING_MIN_DISTANCE = 100, FLING_MIN_VELOCITY = 200;
if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE
&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
// Fling left
Log.i("MyGesture", "Fling left");
Toast.makeText(context, "Fling Left", Toast.LENGTH_SHORT).show();
} else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE
&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
// Fling right
Log.i("MyGesture", "Fling right");
Toast.makeText(context, "Fling Right", Toast.LENGTH_SHORT).show();
}
return true;
}
关于返回值的认知:
如果GestureDetector.SimpleOnGestureListener消耗掉了这个事件,则返回true,否则返回false
当然最后不要忘记在你的Activity中override onTouch方法来获取手势action:
Java代码
@Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event))
return true;
else
return false;
}
1. 点击屏幕上的某项的执行流程 有两种情况,一种是时间很短,一种时间稍长
时间很短:onDown--------》onSingleTapUp--------》onSingleTapConfirmed
时间稍长:onDown--------》onShowPress------》onSingleTapUp--------》onSingleTapConfirmed
2. 长按事件
onDown--------》onShowPress------》onLongPress
3.抛:手指触动屏幕后,稍微滑动后立即松开
onDown-----》onScroll----》onScroll----》onScroll----》………----->onFling
4.拖动
onDown------》onScroll----》onScroll------》onFiling
注意:有的时候会触发onFiling,但是有的时候不会触发,个人理解是人的动作不标准所致。