android之GestureDetector
今天来详细说一下android中常常使用的GestureDetector。先来看看google对GestureDetector的介绍:
/** * Detects various gestures and events using the supplied {@link MotionEvent}s. * The {@link OnGestureListener} callback will notify users when a particular * motion event has occurred. This class should only be used with {@link MotionEvent}s * reported via touch (don't use for trackball events). * * To use this class: * <ul> * <li>Create an instance of the {@code GestureDetector} for your {@link View} * <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call * {@link #onTouchEvent(MotionEvent)}. The methods defined in your callback * will be executed when the events occur. * </ul> */上面主要说了GestureDetector的作用和使用方法,这里我先做一下大意的翻译:GestureDetector可以通过view的onTouchEvent带回的MotionEvent来判断出特殊的手势,当检测到有特殊的手势发生时,就会回调对应的特殊方法来告知用户。
从上述可以知道,对于GestureDetector的使用主要有两个地方需要我们自己来做:
(1)在需要检测手势的view或者activity等 ,需要在其onTouchEvent(MotionEvent event)方法里面实时将event信息传递给你的GestureDetector对象,比如下来这样:
@Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub return this.detector.onTouchEvent(event); }(2)上面说,当有特殊的手势时候会调用特殊的回调方法,所以这里还需要我们去写对于特殊手势的回调函数。GestureDetector里面定义了不同的接口函数来对应不同的手势。所以我们只需要实现GestureDetector里面的手势接口方法即可。
GestureDetector的手势接口分两种:OnGestureListener主要处理单点触摸、OnDoubleTapListener主要是处理两点触摸。一般情况,你希望用到那一种就实现一种的接口就可以了。然后把实现手势接口的对象传递给你的GestureDetector就可以了。
在GestureDetector.java有其对GestureDetector的定义,从中可以看到定义的一个变量 private final OnGestureListener mListener; 其中mListener就是指向我们自己实现手势接口的对象。我们来看看GestureDetector的一个最终的构造函数:
public GestureDetector(Context context, OnGestureListener listener, Handler handler) { if (handler != null) { mHandler = new GestureHandler(handler); } else { mHandler = new GestureHandler(); } mListener = listener; if (listener instanceof OnDoubleTapListener) { setOnDoubleTapListener((OnDoubleTapListener) listener); } init(context); }
public class LightActivity extends Activity implements OnTouchListener, OnGestureListener { private static String MY_PKG_NAME = "com.android.camera"; private LinearLayout mlayout; private GestureDetector detector; // 申明一个<span style="font-family:Arial, Helvetica, sans-serif;">GestureDetector </span>...... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_light); CloseCamera(); mlayout = (LinearLayout) findViewById(R.id.mlayou); detector = new GestureDetector(this); // 实例化一个对象,这里传递的是<span style="font-family:Arial, Helvetica, sans-serif;">LightActivity对象,因为</span><span style="font-family:Arial, Helvetica, sans-serif;">LightActivity实现了</span><span style="font-family:Arial, Helvetica, sans-serif;">OnGestureListener 接口</span><span style="font-family:Arial, Helvetica, sans-serif;"></span><span style="font-family:Arial, Helvetica, sans-serif;"></span> Resources resources = this.getResources();......}...... @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub return this.detector.onTouchEvent(event); // 这里实时将<span style="font-family:Arial, Helvetica, sans-serif;">MotionEvent 传递给我们的</span><span style="font-family:Arial, Helvetica, sans-serif;">detector</span><span style="font-family:Arial, Helvetica, sans-serif;"></span> }......
// 下面你的几个方法是实现接口<span style="font-family:Arial, Helvetica, sans-serif;">OnGestureListener</span> @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub // ᄑᄑᄑᄑ /* * if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) * > FLING_MIN_VELOCITY) { if (IsOpenFlash) { // Fling left * mVibrator.vibrate(off, -1); closeFlashLight(); * mlayout.setBackgroundDrawable(mdrawable_off); } } else if (e2.getX() * - e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > * FLING_MIN_VELOCITY) { if (!IsOpenFlash) { // Fling right * mVibrator.vibrate(on, -1); openFlashLight(); * mlayout.setBackgroundDrawable(mdrawable_on); } } */ return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub // 锟斤拷锟斤拷 if ((e1.getY() > MAX_UP && e2.getY() < MAX_DOWN) && (e1.getX() > MAX_LEFT && e2.getX() < MAX_RIGHT)) { if (e1.getY() - e2.getY() > FLING_MIN_DISTANCE && Math.abs(distanceY) > FLING_MIN_VELOCITY) { if (!IsOpenFlash) { // Fling up mVibrator.vibrate(on, -1); openFlashLight(); mlayout.setBackgroundDrawable(mdrawable_on); } } else if (e2.getY() - e1.getY() > FLING_MIN_DISTANCE && Math.abs(distanceY) > FLING_MIN_VELOCITY) { if (IsOpenFlash) { // Fling down mVibrator.vibrate(off, -1); closeFlashLight(); mlayout.setBackgroundDrawable(mdrawable_off); } } } return false; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; }......}最后我们来介绍一下GestureDetector的手势接口方法:
(1)OnGestureListener
boolean onDown(MotionEvent e); // 点击时候一触摸到屏就会发生
void onShowPress(MotionEvent e); // 在点击触摸到屏时候、并且move or up都还没有发生时候 就会发生。其实就是在onDown之后,原则上第一个会发生的手势。
boolean onSingleTapUp(MotionEvent e); // 当单个点击触摸屏UP(离开)的时候发生的手势,这里为什么是SingleTap呢? 就是要区别多点触摸,所以这里其实是指只有一个手指触摸屏时候,up(离开屏)的时候发生的手势。
void onLongPress(MotionEvent e);// 长按手势
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);// 是指触摸屏的时候,在屏上面滑动的时候发生的手势,其实上是在MotionEvent.ACTION_MOVE的时候才会发生的手势。
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY); // 这个和onScroll不一样,这个主要是用于识别用户在move的时候,突然UP的时候才会发生的手势。velocityX 和velocityY是指速率(这里是一个second移动的距离);MotionEvent e1当前这个手势发生的down motion event ;MotionEvent e2 发生这个手势的move motion event。onFling主要用于判断用户的意图,
对于onFling和onScroll我们来举例说明:onScroll一般用于识别用户对图片的放大、缩小意图;onFling常用于识别用户看电子 书的时候翻页的意图。
(2)OnDoubleTapListener:
boolean onSingleTapConfirmed(MotionEvent e); // 确认只是一次点击的时候发生的手势,这里其实是第一次点击后,一段时间内没有再收到一个一个点击,则发生该手势。这里的一段时间其实就是一点确认是否是双击的时间:ViewConfiguration.getDoubleTapTimeout()。在ViewConfiguration.java里面有其定义时间长度:
/** * Defines the duration in milliseconds between the first tap's up event and * the second tap's down event for an interaction to be considered a * double-tap. */ private static final int DOUBLE_TAP_TIMEOUT = 300;
boolean onDoubleTap(MotionEvent e);// 双击的时候发生的手势。参数:MotionEvent e 是指第一次点击的事件。
boolean onDoubleTapEvent(MotionEvent e);//// 双击发生的过程中发生的手势。
其实GestureDetector的处理核心代码是public boolean onTouchEvent(MotionEvent ev),这个方法做了所有对手势的检测和区分。如还是不太理解各个手势是如何发生的话可以去看看这个方法。
更多相关文章
- [置顶] 调用Android发短信接口Intent.ACTION_SENDTO
- Android中的Parcelable接口
- Android 接口定义语言 (AIDL)
- Android中回调接口的使用
- Android手势滑动Tab
- Android网络应用接口
- android图片缩放手势检测类--ScaleGestureDetector
- Android手势下拉抽屉效果
- Android 滑动手势侦测方法介绍