标签:
识别器GestureDetector基本介绍
当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等。一般情况下,我们可以通过View或Activity的onTouchEvent,或实现OnTouchListener接口后通过onTouch方法,处理一些touch事件,但是这个方法太过简单,如果需要处理一些复杂的手势,用这个接口就会很麻烦(因为我们要自己根据用户触摸的轨迹去判断是什么手势)。为此,Android 给我们提供了GestureDetector类(Gesture:手势,Detector:识别),通过这个类我们可以识别很多的手势,主要是通过他的onTouchEvent方法完成不同手势的识别。虽然他能识别手势,但是不同的手势要怎么处理,还是给程序员自己要实现的。注意:默认情况下,GestureDetector是监听不到MotionEvent事件的,也即GestureDetector的onTouchEvent方法是不会被调用的,若要被调用,必须满足两个条件
- ①在View的onTouchEvent()方法中,须将MotionEvent事件手动【传】给GestureDetector
- ②若View设置了.setOnTouchListener()监听器,则其onTouch()的返回值还须是【false】,或者在onTouch()中将MotionEvent事件手动【传】给GestureDetector
只有这样,GestureDetector 注册的OnGestureListener(单击)或OnDoubleTapListener(双击)才能获得完整的MotionEvent事件,进而根据该对象封装的的信息,做出合适的反馈。
识别器ScaleGestureDetector基本介绍
ScaleGestureDetector是Android2.2 新增的类,其能使 Views 通过接收到的 MotionEvents ,检测包括多点触摸在内的手势变化信息,当检测到此类信息后,监听器OnScaleGestureListener 便会调用相应的回调方法通知用户,其最简单常用的应用场景就是使用双指缩放图片。注意,ScaleGestureDetector是直接继承自object的,并非GestureDetector的子类。监听器OnScaleGestureListener回调方法有onScale(ScaleGestureDetector) 、onScaleBegin、onScaleEndScaleGestureDetector中定义的公共方法:
- public float getCurrentSpan () 返回手势过程中,组成该手势的两个触点的当前距离。
- public long getEventTime () 返回事件被捕捉时的时间。
- public float getFocusX () 返回当前手势焦点的 X 坐标。 如果手势正在进行中,焦点位于组成手势的两个触点之间。 如果手势正在结束,焦点为仍留在屏幕上的触点的位置。若 isInProgress() 返回 false,该方法的返回值未定义。
- public float getFocusY () 返回当前手势焦点的 Y 坐标。
- public float getPreviousSpan () 返回手势过程中,组成该手势的两个触点的前一次距离。
- public float getScaleFactor () 返回从前一个伸缩事件至当前伸缩事件的伸缩比率。该值定义为 getCurrentSpan() / getPreviousSpan()。
- public long getTimeDelta () 返回前一次接收到的伸缩事件距当前伸缩事件的时间差,以毫秒为单位。
- public boolean isInProgress () 如果手势处于进行过程中,返回 true。否则返回 false。
手势监听器SimpleOnGestureListeren
我们只需要继承SimpleOnGestureListener重载自己需要监听的手势即可public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener {}OnGestureListener的监听事件
- 按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下
- 抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作,onDown---onScroll---onScroll---…onFling
- 长按(onLongPress): 手指按在持续一段时间,并且没有松开
- 滚动(onScroll): 手指在触摸屏上滑动,onDown---onScroll---onScroll---…onScroll
- 按住(onShowPress): 手指按在触摸屏上,在按下起效,在长按前失效,onDown->onShowPress->onLongPress
- 抬起(onSingleTapUp):手指离开触摸屏的那一刹那
OnDoubleTapListener的监听事件
- onDoubleTap,双击的【第二下】down时触发(只执行一次)
- onDoubleTapEvent,双击的【第二下】down和up都会触发(执行次数不确定)
- onSingleTapConfirmed单击确认,即很快的按下并抬起,但并不连续点击第二下
注意:
- onSingleTapConfirmed(单击)和onSingleTapUp都是在down后既没有滑动onScroll,又没有长按onLongPress时, up 时触发的
- 非常快的点击一下:onDown->onSingleTapUp->onSingleTapConfirmed
- 稍微慢点的点击一下:onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed(最后一个不一定会触发)
演示代码-在Activity中使用
上面的图片是添加了GestureDetector和ScaleGestureDetector的ImageView,并且在【onTouchEvent】方法中将事件传递给手势识别器,且返回【true】
下面的图片是在上面图片基础上注册了【OnTouchListener】,若在其【onTouch】方法中返回【true】,则就会导致其注册的手势识别器全部失效!
我们为Activity自身注册了GestureDetector和ScaleGestureDetector,并且在其【onTouchEvent】方法中将事件传递给手势识别器,返回值使用默认逻辑值public class MainActivity extends Activity {private GestureDetector mGestureDetector;//用于Activity自身的单击和双击事件手势识别器private ScaleGestureDetector mScaleGestureDetector;//用于Activity自身的缩放事件手势识别器@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyImageView myImageView = (MyImageView) findViewById(R.id.iv);myImageView.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {return true;//返回值要为false,或者直接在此onTouch()中将MotionEvent事件手动传给GestureDetector,才能使手势识别器生效}});//**************************************************************************************************************************mGestureDetector = new GestureDetector(this, new SimpleOnGestureListener() {@Override//监测双击事件public boolean onDoubleTap(MotionEvent e) {Log.e("Activity-手势", "onDoubleTap");return super.onDoubleTap(e);}});mScaleGestureDetector = new ScaleGestureDetector(this, new SimpleOnScaleGestureListener() {@Override//监测缩放public boolean onScale(ScaleGestureDetector detector) {DecimalFormat df = new DecimalFormat("0.00");//格式化floatLog.e("Activity-缩放", "onScale," + df.format(detector.getScaleFactor()) + "-" + //缩放因子,两指靠拢时小于1df.format(detector.getFocusX()) + "-" + df.format(detector.getFocusY()));//中心点坐标return super.onScale(detector);}});}//**************************************************************************************************************************@Override//重写屏幕触摸事件onTouchEvent,将触摸事件传给GestureDetectorpublic boolean onTouchEvent(MotionEvent event) {try {//在onTouchEvent方法中可以完成所有GestureDetector的操作,因为他们都只需要一个MotionEvent的参数Log.e("Activity-多点触摸", "onTouchEvent" + spacing(event));} catch (Exception e) {}mGestureDetector.onTouchEvent(event);mScaleGestureDetector.onTouchEvent(event);return super.onTouchEvent(event);}/*** 返回两个点之间的距离*/private float spacing(MotionEvent event) {float x = event.getX(0) - event.getX(1);float y = event.getY(0) - event.getY(1);return FloatMath.sqrt(x * x + y * y);}}
演示代码-在View中使用
public class MyImageView extends ImageView {private GestureDetector mGestureDetector;//单击和双击事件手势识别private ScaleGestureDetector mScaleGestureDetector;//缩放事件手势识别public MyImageView(Context context) {this(context, null);}public MyImageView(Context context, AttributeSet attr) {super(context, attr);mGestureDetector = new GestureDetector(context, new MyGestureListener());mScaleGestureDetector = new ScaleGestureDetector(context, new MyScaleGestureListener());}@Overridepublic boolean onTouchEvent(MotionEvent event) {mGestureDetector.onTouchEvent(event);mScaleGestureDetector.onTouchEvent(event);//return super.onTouchEvent(event);//不管返回值是什么,都能接收down事件,都能触发onDown、onShowPress、onLongPressreturn true;//但只有返回true才能继续接收move,up等事件,也才能响应ScaleGestureDetector事件及GestureDetector中与move,up相关的事件}//**************************************************************************************************************************private class MyScaleGestureListener extends SimpleOnScaleGestureListener {@Overridepublic boolean onScale(ScaleGestureDetector detector) {Log.e("view-缩放", "onScale," + detector.getScaleFactor());return super.onScale(detector);}@Overridepublic boolean onScaleBegin(ScaleGestureDetector detector) {Log.e("view-缩放", "onScaleBegin");return super.onScaleBegin(detector);}@Overridepublic void onScaleEnd(ScaleGestureDetector detector) {Log.e("view-缩放", "onScaleEnd");}}//**************************************************************************************************************************private class MyGestureListener extends SimpleOnGestureListener {@Override//双击的【第二下】Touch down时触发(只执行一次)public boolean onDoubleTap(MotionEvent e) {Log.e("view-手势", "onDoubleTap");return super.onDoubleTap(e);}@Override//双击的【第二下】Touch down和up都会触发(执行次数不确定)。public boolean onDoubleTapEvent(MotionEvent e) {Log.e("view-手势", "onDoubleTapEvent");return super.onDoubleTapEvent(e);}@Override//Touch down时触发public boolean onDown(MotionEvent e) {Log.e("view-手势", "onDown");return super.onDown(e);}@Override//onScroll一点距离后,【抛掷时】触发(若是轻轻的、慢慢的停止活动,而非抛掷,则很可能不触发)//参数为手指接触屏幕、离开屏幕一瞬间的动作事件,及手指水平、垂直方向移动的速度,像素/秒public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {Log.e("view-手势", "onFling");if ((e2.getRawX() - e1.getRawX()) > 100) {Log.e("view-手势", "onFling-从左到右滑");return true;}return super.onFling(e1, e2, velocityX, velocityY);}@Override//Touch了不移动一直Touch down时触发public void onLongPress(MotionEvent e) {Log.e("view-手势", "onLongPress");super.onLongPress(e);}@Override//Touch了滑动时触发,e1代表触摸时的事件,是不变的,e2代表滑动过程中的事件,是时刻变化的//distance是当前event2与上次回调时的event2之间的距离,代表上次回调之后到这次回调之前移动的距离public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {Log.e("view-手势", "onScroll-" + (int) e1.getX() + "-" + (int) e2.getX() + "-" + (int) distanceX + "-" + (int) distanceY);return super.onScroll(e1, e2, distanceX, distanceY);}@Override//Touch了还没有滑动时触发public void onShowPress(MotionEvent e) {Log.e("view-手势", "onShowPress");super.onShowPress(e);}@Override//在touch down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touchup时触发。public boolean onSingleTapConfirmed(MotionEvent e) {Log.e("view-手势", "onSingleTapConfirmed");return super.onSingleTapConfirmed(e);}@Override//在touch down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touchup时触发。public boolean onSingleTapUp(MotionEvent e) {Log.e("view-手势", "onSingleTapUp");return super.onSingleTapUp(e);}}}
布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"android:layout_height="match_parent"android:background="#1234"android:orientation="vertical" ><com.bqt.test.MyImageViewandroid:layout_width="match_parent"android:layout_height="150dp"android:background="#10ff"android:src="@drawable/ic_launcher" /><com.bqt.test.MyImageViewandroid:id="@+id/iv"android:layout_width="match_parent"android:layout_height="150dp"android:background="#1f00"android:src="@drawable/ic_launcher" /></LinearLayout>
手势识别 GestureDetector ScaleGestureDetector
标签:
原文地址:http://www.cnblogs.com/baiqiantao/p/5630506.html