手势 触摸【缩放】GestureDetector MotionEvent 案例

GestureDetector和ScaleGestureDetector示例

/**

* 演示【单点触摸手势识别器】

* 演示【缩放手势识别器】最简单的使用

* @author 白乾涛

*/

public class FirstActivity extends Activity implements OnTouchListener {

private ImageView iv;

private GestureDetector mGestureDetector;//单击和双击事件手势识别器

private ScaleGestureDetector mScaleGestureDetector;//缩放事件手势识别器

private Matrix matrix = new Matrix();

private DecimalFormat df = new DecimalFormat("0.00");//格式化float

private float lastScale = 1;//记录上次的缩放比例,下次缩放时是在此基础上进行的

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

iv = new ImageView(this);

iv.setImageResource(R.drawable.ic_launcher);

iv.setScaleType(ScaleType.MATRIX);//用矩阵来绘制

setContentView(iv);

mGestureDetector = new GestureDetector(this, new MyGestureListener());

mScaleGestureDetector = new ScaleGestureDetector(this, new SimpleOnScaleGestureListener() {

@Override

public boolean onScale(ScaleGestureDetector detector) {

float scale = detector.getScaleFactor(); //缩放因子,两指靠拢时小于1

float x = detector.getFocusX(), y = detector.getFocusY();//中心点坐标

Log.i("bqt", "缩放手势  onScale," + df.format(scale) + "-" + df.format(x) + "-" + df.format(y));

matrix.setScale(lastScale * scale, lastScale * scale);

iv.setImageMatrix(matrix);

return super.onScale(detector);

}

@Override

public boolean onScaleBegin(ScaleGestureDetector detector) {

Log.i("bqt", "缩放手势  onScaleBegin," + df.format(detector.getScaleFactor()));//始终是1

return super.onScaleBegin(detector);

}

@Override

public void onScaleEnd(ScaleGestureDetector detector) {

super.onScaleEnd(detector);

lastScale *= detector.getScaleFactor();

Log.i("bqt", "缩放手势  onScaleEnd," + df.format(detector.getScaleFactor()));

}

});

}

@Override

public boolean onTouchEvent(MotionEvent event) {

mGestureDetector.onTouchEvent(event);

mScaleGestureDetector.onTouchEvent(event);

return super.onTouchEvent(event);

}

@Override

public boolean onTouch(View v, MotionEvent event) {

return false;//设置OnTouchListener时,返回值要为false,或者在onTouch()中将MotionEvent事件传给GestureDetector,才能使手势识别器生效

}

class MyGestureListener extends SimpleOnGestureListener {

@Override

//双击的【第二下】Touch down时触发(只执行一次)

public boolean onDoubleTap(MotionEvent e) {

Log.i("bqt", "onDoubleTap");

return super.onDoubleTap(e);

}

@Override

//双击的【第二下】Touch down和up都会触发(执行次数不确定)。

public boolean onDoubleTapEvent(MotionEvent e) {

Log.i("bqt", "onDoubleTapEvent");

return super.onDoubleTapEvent(e);

}

@Override

//Touch down时触发

public boolean onDown(MotionEvent e) {

Log.i("bqt", "onDown");

return super.onDown(e);

}

@Override

//onScroll一点距离后,【抛掷时】触发(若是轻轻的、慢慢的停止活动,而非抛掷,则很可能不触发)

//参数为手指接触屏幕、离开屏幕一瞬间的动作事件,及手指水平、垂直方向移动的速度,像素/秒

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

Log.i("bqt", "onFling");

if ((e2.getRawX() - e1.getRawX()) > 100) {

Log.i("bqt", "onFling-从左到右滑");

return true;//消耗事件

}

return super.onFling(e1, e2, velocityX, velocityY);

}

@Override

//Touch了不移动一直Touch down时触发

public void onLongPress(MotionEvent e) {

Log.i("bqt", "onLongPress");

super.onLongPress(e);

}

@Override

//Touch了滑动时触发,e1代表触摸时的事件,是不变的,e2代表滑动过程中的事件,是时刻变化的

//distance是当前event2与上次回调时的event2之间的距离,代表上次回调之后到这次回调之前移动的距离

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

Log.i("bqt", "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.i("bqt", "onShowPress");

super.onShowPress(e);

}

@Override

//在touch down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touchup时触发。

public boolean onSingleTapConfirmed(MotionEvent e) {

Log.i("bqt", "onSingleTapConfirmed");

return super.onSingleTapConfirmed(e);

}

@Override

//在touch down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touchup时触发。

public boolean onSingleTapUp(MotionEvent e) {

Log.i("bqt", "onSingleTapUp");

return super.onSingleTapUp(e);

}

}

}

MotionEvent示例:缩放图片

public class SecondActivity extends Activity implements OnTouchListener {

private ImageView iv;

private float scale = 1;

private float lastScale = 1;//记录手指全部离开时的缩放比例,下次缩放时是在此基础上进行的

private float oldDist;//记录第二个触摸点和第一个触摸点之间的距离

private Matrix mMatrix = new Matrix();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

iv = new ImageView(this);

iv.setImageResource(R.drawable.ic_launcher);

iv.setBackgroundColor(0x8822ffff);//从背景可以看出,此ImageView 是占用整个屏幕大小的

iv.setScaleType(ScaleType.MATRIX);

iv.setOnTouchListener(this);

setContentView(iv);

}

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getActionMasked()) {

case MotionEvent.ACTION_DOWN:

Log.i("bqt", "ACTION_DOWN,第一个触摸点,所以肯定为【1】" + event.getPointerCount());

break;

case MotionEvent.ACTION_UP://当屏幕上唯一的点被放开时触发

lastScale = scale;//记录手指全部离开时的缩放比例,下次缩放时是在此基础上进行的

Log.i("bqt", "ACTION_UP,最后一个触摸点,之前触摸点数肯定为【1】" + event.getPointerCount());

break;

case MotionEvent.ACTION_POINTER_UP://当屏幕上有多个点被按住,松开其中一个点时触发

Log.i("bqt", "ACTION_POINTER_UP,少一个触摸点,少之前的触摸点数为" + event.getPointerCount());

break;

case MotionEvent.ACTION_POINTER_DOWN://当屏幕上已经有一个点被按住,此时再按下其他点时触发

if (event.getPointerCount() == 2) oldDist = spacing(event);//记录第二个触摸点和第一个触摸点之间的距离

Log.i("bqt", "ACTION_POINTER_DOWN,又一个触摸点,目前触摸点数为" + event.getPointerCount());

break;

case MotionEvent.ACTION_MOVE://当有点在屏幕上移动时触发

if (event.getPointerCount() == 2) {

float newDist = spacing(event);//移动过程中,第二个点和第一个点的距离

if (Math.abs(newDist - oldDist) > 10) {//减小灵敏度

scale = lastScale * newDist / oldDist;

Log.i("bqt", "ACTION_MOVE,缩放比例为" + scale);

mMatrix.setScale(scale, scale);

iv.setImageMatrix(mMatrix);

}

}

break;

}

return true;

}

/**

* 返回两个点之间的距离

*/

private float spacing(MotionEvent event) {

if (event.getPointerCount() >= 2) {

float x = event.getX(0) - event.getX(1);

float y = event.getY(0) - event.getY(1);

return (float) Math.sqrt(x * x + y * y);

} else return 0;

}

}

MotionEvent示例:功能增强

public class ThirdActivity extends Activity implements OnTouchListener {

private ImageView imageView;

private Matrix startMatrix = new Matrix();//ImageView初始矩阵

private Matrix matrix = new Matrix();//要给ImageView设置的矩阵

private float startDis;//两个手指的按下时的初始距离

private PointF midPoint;//两个手指的按下时中间点

private PointF startPoint = new PointF();//第一个手指按下时的坐标位置

private boolean isPointerUp;//当有手指放开时,如果不停止缩放,会导致图片位置错乱。后续可以优化

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

imageView = new ImageView(this);

imageView.setImageResource(R.drawable.ic_launcher);

imageView.setOnTouchListener(this);

imageView.setScaleType(ScaleType.MATRIX);

setContentView(imageView);

}

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getActionMasked()) {

case MotionEvent.ACTION_DOWN:

Log.i("bqt", "初始矩阵" + imageView.getImageMatrix());//值是会变的 {[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}

startMatrix.set(imageView.getImageMatrix());//获取初始状态

startPoint.set(event.getX(), event.getY());//获取开始时候的坐标位置

isPointerUp = true;

break;

case MotionEvent.ACTION_MOVE:

if (isPointerUp) {

if (event.getPointerCount() == 1) { //移动图片

float dx = event.getX() - startPoint.x; // 得到X轴的移动距离

float dy = event.getY() - startPoint.y; // 得到Y轴的移动距离

Log.i("bqt", "移动距离" + (int) dx + "---" + (int) dy);

matrix.set(startMatrix);//先置为初始状态

matrix.postTranslate(dx, dy);

} else if (event.getPointerCount() == 2) { // 放大缩小图片

float endDis = distance(event);// 距离

float scale = endDis / startDis;//ImageView缩放的比例

Log.i("bqt", "缩放倍数" + scale);

matrix.set(startMatrix);

matrix.postScale(scale, scale, midPoint.x, midPoint.y);

}

imageView.setImageMatrix(matrix);

}

break;

case MotionEvent.ACTION_POINTER_DOWN:

startDis = distance(event);

midPoint = mid(event);

startMatrix.set(imageView.getImageMatrix());//重置为目前的初始状态

break;

case MotionEvent.ACTION_UP:

break;

case MotionEvent.ACTION_POINTER_UP:

isPointerUp = false;

break;

}

return true;

}

/** 计算两个手指间的距离 */

private float distance(MotionEvent event) {

float dx = event.getX(1) - event.getX(0);

float dy = event.getY(1) - event.getY(0);

/** 使用勾股定理返回两点之间的距离 */

return (float) Math.sqrt(dx * dx + dy * dy);

}

/** 计算两个手指间的中间点 */

private PointF mid(MotionEvent event) {

float midX = (event.getX(1) + event.getX(0)) / 2;

float midY = (event.getY(1) + event.getY(0)) / 2;

return new PointF(midX, midY);

}

}

附件列表

时间: 2024-08-05 19:36:17

手势 触摸【缩放】GestureDetector MotionEvent 案例的相关文章

Android手势监听(GestureDetector类)

public class GestureTest extends Activity implements OnClickListener, OnGestureListener { // 定义手势检测器实例 GestureDetector detector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.a

ImageView根据手势进行缩放,拖动

 package com.example.scale; import android.content.Context; import android.graphics.Matrix; import android.graphics.PointF; import android.util.AttributeSet; import android.util.FloatMath; import android.view.MotionEvent; import android.widget.Imag

Android 手势&触摸事件

在刚开始学Android的时候,就觉得Google的文档不咋样,在研究手势时,更加的感觉Google的文档写得实在是太差了.很多常量,属性和方法,居然连个描述都没有.没有描述也就罢了,但是OnGestureListener里手势这么多,它也没有一个介绍说明,在没有进行不断才尝试之前,谁能搞懂onLongPress和onShowPress,onScroll和onFling的关系与差别吗?Google真的需要在文档方面做一次大手术了.不过好在经过鄙人不断反复的尝试.从个人的角度为这几个手势动作做出了

触摸事件 Touch MotionEvent ACTION

MotionEvent简介 当用户触摸屏幕时,将创建一个MontionEvent对象,MotionEvent包含了关于发生触摸的位置.时间信息,以及触摸事件的其他细节. 获取MontionEvent对象的方法有: 在View或Activity的onTouchEvent方法中: public boolean onTouchEvent(MotionEvent event) {} 实现OnTouchListener接口后在onTouch方法中: public boolean onTouch(View 

Android多点触摸缩放图片-android学习之旅(四)

获取多触摸点 核心代码: 获取触摸点的个数和位置 public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("down"); break; case MotionEvent.ACTION_UP: System.out.println("触摸点的个数:"+event.g

Android 触摸手势基础 官方文档概览2

Android 触摸手势基础 官方文档概览 触摸手势检测基础 手势检测一般包含两个阶段: 1.获取touch事件数据 2.解析这些数据,看它们是否满足你的应用所支持的某种手势. 相关API: MotionEvent 兼容版的: MotionEventCompat  (Note that MotionEventCompat is not a replacement for the MotionEvent class. Rather, it provides static utility metho

Android 触摸手势基础 官方文档概览

触摸手势检测基础 手势检测一般包含两个阶段: 1.获取touch事件数据 2.解析这些数据,看它们是否满足你的应用所支持的某种手势. 相关API: MotionEvent 兼容版的: MotionEventCompat  (Note that MotionEventCompat is not a replacement for the MotionEvent class. Rather, it provides static utility methods to which you pass y

android项目 之 记事本(14) ----- 手势缩放与拖拽图片

本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 上节实现了查看图片及录音的功能,其中查看图片,可以调用系统的图库来查看图片,也可以自定义Activity来查看图片,今天就在上节的基础上,实现手势缩放与拖拽图片. 想必大家都用过系统的图库,浏览图片时,可以通过手势放大或缩小图片,旋转图片,拖拽图片等功能,我们也为自已定义的查看图片的Activity增加手势缩放与拖拽图片的功能,效果如下图: 上面四幅图中,演示了通过手势(多点触

触摸、手势

触摸: 1.创建一个视图,重写TA在不同阶段的触发的方法,方法如下: 2.当重写触碰移动方法,想要实现一个视图随着自己的鼠标移动的方法时 获取触摸在屏幕上的手指对象: UITouch *tou = [touches anyObject]; (1)要获取手指移动之前的位置 之前的位置 = [tou previousLocationInView:self] (2)要获取手指移动之后的位置 之后的位置 = [tou locationInView]; (3)视图现在的位置的X值就是: 自己原来的位置 +