GestureDetector 的作用:
检测各种手势和事件,使用的使用一般和onTouchEvent 方法结合在一起使用
下面主要说的内容是GestureDetector 和ScaleGestureDetector
1GestureDetector
里面有一些回调接口下面说下
1.1OnGestureListener 这个是接口,实现的时候里面的方法会自动生成,
1.2SimpleOnGestureListener 这个是静态的里面的方法需要自己重写,就是有时候不需要让生成一大堆的方法,可以使用
这个(平时开发可是使用SimpleOnGestureListener基本满足打说需求)
1.3OnDoubleTapListener 这个是接口里面3个方法SimpleOnGestureListener都有,所以这个就不说了,
1.4OnContextClickListener 这个也是接口里面有1个方法SimpleOnGestureListener都有,所以这个就不说了,
所以建议大家项目开发中使用SimpleOnGestureListener 包含了其他的三个的所有方法,需要的时候重写一些方法即可,下面
下2个demo 仅供参考
OnGestureListener 这个是接口,实现的时候里面的方法会自动生成,
(1)boolean onDown(MotionEvent e);// 按下事件
(2)public void onShowPress(MotionEvent e) //用户已执行down{@link MotionEvent}但未执行 一个移动或上升。此事件通常用于提供 反馈给用户,让他们知道他们的行为 识别,即突出显示一个元素
(3)public boolean onSingleTapUp(MotionEvent e) //在按下并抬起时发生, 使用up{@link MotionEvent}进行点击时通 触发了它。 @param e完成第一次点击的向上运动事件 @如果事件被消耗,则返回true,否则返回false
(4)public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) //在屏幕上滑动 @param e1开始滚动的第一个向下运动事件。 @param e2触发当前onScroll的移动动作事件。@param distanceX自上一次滚动以来沿X轴的距离onScroll。这不是{@code e1}之间的距离和{@code e2}。 @param distance自上一次滚动以来沿Y轴的距 *onScroll。这不是{@code e1}之间的距离和{@code e2}。 @return true如果事件被消耗,否则为false
(5)onLongPress // 长按事件
(6)onFling // 按下触摸屏、快速移动后松开 @param e1开始投掷的第一个向下运动事件。 @param e2触发当前触发的移动动作事件。 @param velocityX这个投掷的速度,以像素每秒为单位 沿x轴。 @param velocityY这个投掷的速度,以像素每秒为单位 沿y轴。 @return true如果事件被消耗,否则为false
下面开始写一个demo 看看GestureDetector ,写一个点击的时候图片移动到点击的位置
下面看下代码:
public class TestView extends View {// paint 初始化private Paint paint;private Bitmap bitmap;private int mPointX;private int mPointY;private static String TAG = "---------gestureDetector";public TestView(Context context) {super(context);}public TestView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context, attrs);}public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}private void init(Context context, AttributeSet attrs) {paint = new Paint();// paint.setColor(Color.RED);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.girl);canvas.drawBitmap(bitmap, mPointX, mPointY, paint);}@Overridepublic boolean onTouchEvent(MotionEvent event) {return gestureDetector.onTouchEvent(event);}GestureDetector gestureDetector = new GestureDetector(getContext(),new GestureDetector.OnGestureListener() {// 按下@Overridepublic boolean onDown(MotionEvent e) {Log.e(TAG, "onDown");mPointX = (int) e.getX();mPointY = (int) e.getY();invalidate();return false;}/**用户已执行down{@link MotionEvent}但未执行一个移动或上升。此事件通常用于提供反馈给用户,让他们知道他们的行为识别,即突出显示一个元素**/@Overridepublic void onShowPress(MotionEvent e) {Log.e(TAG, "onShowPress");}/*** 使用up{@link MotionEvent}进行点击时通* 触发了它。* @param e完成第一次点击的向上运动事件* @如果事件被消耗,则返回true,否则返回false* @param e* @return*/@Overridepublic boolean onSingleTapUp(MotionEvent e) {Log.e(TAG, "onSingleTapUp");return false;}/*** 在屏幕上滑动* @param e1开始滚动的第一个向下运动事件。* @param e2触发当前onScroll的移动动作事件。* @param distanceX自上一次滚动以来沿X轴的距离* onScroll。这不是{@code e1}之间的距离和{@code e2}。* @param distance自上一次滚动以来沿Y轴的距* onScroll。这不是{@code e1}之间的距离和{@code e2}。* *@return true如果事件被消耗,否则为false* @param e1* @param e2* @param distanceX* @param distanceY* @return*/@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY) {Log.e(TAG, "onScroll");return false;}// 长按@Overridepublic void onLongPress(MotionEvent e) {Log.e(TAG, "onLongPress");}/*** 按下触摸屏、快速移动后松开* *@param e1开始投掷的第一个向下运动事件。* *@param e2触发当前触发的移动动作事件。* *@param velocityX这个投掷的速度,以像素每秒为单位* *沿x轴。* *@param velocityY这个投掷的速度,以像素每秒为单位* *沿y轴。* *@return true如果事件被消耗,否则为false* @param e1* @param e2* @param velocityX* @param velocityY* @return*/@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {Log.e(TAG, "onFling");return false;}});}
可能有人说使用onTouchEvent 就可以实现了,这里只是简单的熟悉GestureDetector使用,
1.2 SimpleOnGestureListener 这个是静态的里面的方法需要自己重写,就是有时候不需要让生成一大堆的方法,可以使用
这个 但是里面多了几个方法
(1)onSingleTapConfirmed :这个回顾下onSingleTapUp在按下并抬起时发生,onSingleTapConfirmed是在按下并抬起时发生但是多了个附加条件就是会确保单击之后短时间内没有再次单击,
(2)onDoubleTap:双击的第二下Touch down时触发
(3)onDoubleTapEvent:双击的第二下Touch down和up都会触发
其他的事件基本一样
下面使用SimpleOnGestureListener 写一个写一个点击图片放大的效果
public class TestView extends View {// paint 初始化private Paint paint;private Bitmap bitmap;private Matrix matrix = new Matrix();private static String TAG = "---------gestureDetector";public TestView(Context context) {super(context);}public TestView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context, attrs);}public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}private void init(Context context, AttributeSet attrs) {paint = new Paint();// paint.setColor(Color.RED);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.girl);canvas.drawBitmap(bitmap, matrix, paint);}@Overridepublic boolean onTouchEvent(MotionEvent event) {return gestureDetector.onTouchEvent(event);}GestureDetector gestureDetector = new GestureDetector(getContext(),new GestureDetector.SimpleOnGestureListener() {@Overridepublic boolean onDown(MotionEvent e) {matrix.postScale(1.5f, 1.5f);invalidate();return super.onDown(e);}});}
2ScaleGestureDetector 手势的缩放
使用方法和GestureDetector 差不多,
里面的接口回调方法如下
2.1OnScaleGestureListener 是接口使用的时候回自动生成3个方法
(1)onScale 缩放进行中
(2)onScaleBegin 缩放开始
(3)onScaleEnd 缩放结束
2.2SimpleOnScaleGestureListener 这个是静态的类 的三个方法和OnScaleGestureListener 一样,不过用到的时候需要重写一下
下面是一个demo 实现图片的缩放,效果出现了边界,没有限制,这里只是演示OnScaleGestureListener 使用,实现图片可以缩放了,
public class TestView extends View {// paint 初始化private Paint paint;private Bitmap bitmap;private float scaleX;private float scaleY;Matrix matrix = new Matrix();private static String TAG = "---------gestureDetector";public TestView(Context context) {super(context);}public TestView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context, attrs);}public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}private void init(Context context, AttributeSet attrs) {paint = new Paint();// paint.setColor(Color.RED);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.girl);canvas.drawBitmap(bitmap, matrix, paint);}float[] m = new float[9];private float getMatrixScaleY() {matrix.getValues(m);return m[4];}@Overridepublic boolean onTouchEvent(MotionEvent event) {return scaleGestureDetector.onTouchEvent(event);}ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(getContext(),new ScaleGestureDetector.OnScaleGestureListener() {@Overridepublic boolean onScale(ScaleGestureDetector detector) {float scaleFactor = detector.getScaleFactor();Log.e("--------onScale", String.valueOf(scaleFactor));scaleX = detector.getCurrentSpanX();scaleY = detector.getCurrentSpanY();Log.e("--------scaleX", String.valueOf(scaleX));Log.e("--------scaleY", String.valueOf(scaleY));if (getMatrixScaleY() * scaleFactor > 2) {scaleFactor = 2 / getMatrixScaleY();}if (getMatrixScaleY() * scaleFactor < 0.5) {scaleFactor = 0.5f / getMatrixScaleY();}matrix.postScale(scaleFactor, scaleFactor, scaleX, scaleY);invalidate();return true;}@Overridepublic boolean onScaleBegin(ScaleGestureDetector detector) {Log.e("--------onScaleBegin", String.valueOf(detector.getScaleFactor()));return true;}@Overridepublic void onScaleEnd(ScaleGestureDetector detector) {Log.e("--------onScaleEnd", String.valueOf(detector.getScaleFactor()));}});}