Android VersionedGestureDetector手势事件
今天研究了一下PhotoView,发现里面的自定义的手势事件可以支持所有的SDK版本,该事件可以实现拖拽、滑动、缩放功能。下面直接上代码:
public abstract class VersionedGestureDetector {
static final String LOG_TAG = "VersionedGestureDetector";
OnGestureListener mListener;
public static VersionedGestureDetector newInstance(Context context, OnGestureListener listener) {
final int sdkVersion = Build.VERSION.SDK_INT;
VersionedGestureDetector detector = null;
if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
detector = new CupcakeDetector(context);
} else if (sdkVersion < Build.VERSION_CODES.FROYO) {
detector = new EclairDetector(context);
} else {
detector = new FroyoDetector(context);
}
detector.mListener = listener;
return detector;
}
public abstract boolean onTouchEvent(MotionEvent ev);
public abstract boolean isScaling();
public static interface OnGestureListener {
public void onDrag(float dx, float dy);
public void onFling(float startX, float startY, float velocityX, float velocityY);
public void onScale(float scaleFactor, float focusX, float focusY);
}
// <2.0
private static class CupcakeDetector extends VersionedGestureDetector {
float mLastTouchX;
float mLastTouchY;
final float mTouchSlop;
final float mMinimumVelocity;
public CupcakeDetector(Context context) {
final ViewConfiguration configuration = ViewConfiguration.get(context);
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mTouchSlop = configuration.getScaledTouchSlop();
}
private VelocityTracker mVelocityTracker;
private boolean mIsDragging;
float getActiveX(MotionEvent ev) {
return ev.getX();
}
float getActiveY(MotionEvent ev) {
return ev.getY();
}
public boolean isScaling() {
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(ev);
mLastTouchX = getActiveX(ev);
mLastTouchY = getActiveY(ev);
mIsDragging = false;
break;
}
case MotionEvent.ACTION_MOVE: {
final float x = getActiveX(ev);
final float y = getActiveY(ev);
final float dx = x - mLastTouchX, dy = y - mLastTouchY;
if (!mIsDragging) {
// Use Pythagoras to see if drag length is larger than
// touch slop
mIsDragging = FloatMath.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
}
if (mIsDragging) {
mListener.onDrag(dx, dy);
mLastTouchX = x;
mLastTouchY = y;
if (null != mVelocityTracker) {
mVelocityTracker.addMovement(ev);
}
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
if (mIsDragging) {
mIsDragging = false;
if (null != mVelocityTracker) {
mLastTouchX = getActiveX(ev);
mLastTouchY = getActiveY(ev);
// Compute velocity within the last 1000ms
mVelocityTracker.addMovement(ev);
mVelocityTracker.computeCurrentVelocity(1000);
final float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker.getYVelocity();
// If the velocity is greater than minVelocity, call
// listener
if (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) {
mListener.onFling(mLastTouchX, mLastTouchY, -vX, -vY);
}
}
}
// Recycle Velocity Tracker
if (null != mVelocityTracker) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
break;
}
}
return true;
}
}
// =2.0 =2.1
private static class EclairDetector extends CupcakeDetector {
private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private int mActivePointerIndex = 0;
public EclairDetector(Context context) {
super(context);
}
@Override
float getActiveX(MotionEvent ev) {
try {
return ev.getX(mActivePointerIndex);
} catch (Exception e) {
return ev.getX();
}
}
@Override
float getActiveY(MotionEvent ev) {
try {
return ev.getY(mActivePointerIndex);
} catch (Exception e) {
return ev.getY();
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = ev.getPointerId(0);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mActivePointerId = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP:
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = ev.getPointerId(newPointerIndex);
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
}
break;
}
mActivePointerIndex = ev.findPointerIndex(mActivePointerId != INVALID_POINTER_ID ? mActivePointerId : 0);
return super.onTouchEvent(ev);
}
}
// >=2.2 add a ScaleGestureDetector
private static class FroyoDetector extends EclairDetector implements ScaleGestureDetector.OnScaleGestureListener {
private ScaleGestureDetector mDetector;
public FroyoDetector(Context context) {
super(context);
mDetector = new ScaleGestureDetector(context, this);
}
@Override
public boolean isScaling() {
return mDetector.isInProgress();
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
mListener.onScale(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY());
return true;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
mDetector.onTouchEvent(ev);
return super.onTouchEvent(ev);
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
// NO-OP
}
}
}
Android VersionedGestureDetector手势事件的更多相关文章
- Qt for android触摸手势事件QGestureEvent
在触摸设备上可以使用Qt的手势事件 要激活手势事件,需要执行以下操作: 第一步,为QWidget控件注册手势事件 QList<Qt::GestureType> gestures; gest ...
- surface上的手势事件
surface上的手势事件 1.surface上的触控事件测试. 手指触控在CHROME和FIREFOX下会触发touch事件,而IE10是不支持touch事件的. 手指触控在三个浏览器下均会触发全部 ...
- Android 触摸手势基础 官方文档概览
Android 触摸手势基础 官方文档概览 触摸手势检测基础 手势检测一般包含两个阶段: 1.获取touch事件数据 2.解析这些数据,看它们是否满足你的应用所支持的某种手势. 相关API: Moti ...
- android GestureDetector 手势基础
1. 当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等等,我们知道View类有个View.OnTouchListener内部接口,通过重写他的onTouch(Vi ...
- Android 触摸手势基础 官方文档概览2
Android 触摸手势基础 官方文档概览 触摸手势检测基础 手势检测一般包含两个阶段: 1.获取touch事件数据 2.解析这些数据,看它们是否满足你的应用所支持的某种手势. 相关API: Moti ...
- JavaScript触摸与手势事件
JavaScript触摸与手势事件 发表于 2012-12-10 由 admin iOS版Safari为了向开发人员传达一些特殊信息,新增了一些专有事件.因为iOS设备既没有鼠标也没有键盘,所以在为移 ...
- Javascript高级编程学习笔记(69)—— 事件(13)触摸与手势事件
触摸与手势事件 由于移动设备既没有鼠标也没有键盘,所以在为移动浏览器开发交互性网页时,常规的鼠标键盘事件根本不够用 所以早期的苹果为Safari 添加了一些与触摸相关的事件 随着后面Android的W ...
- Android View 的事件分发原理解析
作为一名 Android 开发者,每天接触最多的就是 View 了.Android View 虽然不是四大组件,但其并不比四大组件的地位低.而 View 的核心知识点事件分发机制则是不少刚入门同学的拦 ...
- Android触碰事件
OnTouchListener使用 public class ViewActivity extends Activity implements View.OnTouchListener { @Over ...
随机推荐
- 【Linux系统】防暴力破解
在日志文件/var/log/secure 中可以看到涉及到安全方面的日志,可以查看是否有人尝试暴力破解及是否成功,对于肉鸡行为有一定帮助 思路基本上都是加强密码的复杂度,增加iptables配置黑名单 ...
- css-高度自适应的问题(body高度问题)
css-高度自适应的问题 对象height:100%并不能直接产生效果,是因为跟其父对象有关. #center{ height:100%; } 上面的css样式是无效的,不会产生任何效果. 需要改写: ...
- fushioncharts的使用教程
FusionCharts 是使用javascript 实现统计图表的js组件:其官网地址:http://www.fusioncharts.com.其早期版本FusionCharts Free 是基于f ...
- 【bzoj1027】合金
[bzoj1027]合金 分析 数形结合+计算几何+Floyd最小环. http://blog.csdn.net/popoqqq/article/details/40539273 虽然这样占大家的很不 ...
- echarts折线图--数据交互
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- CentOS 6.x启动时网卡eth0未激活
简述 安装CentOS 6.x操作系统后,开机时发现没有网络,最后发现系统启动时未激活网卡 - 因为只有在激活状态的网卡才能去连接网络,进行网络通讯. 简述 激活网卡eth0 激活网卡eth0 执行& ...
- (14)odoo加载机制
Odoo的启动通过openerp-server脚本完成,它是系统的入口. 然后加载配置文件openerp-server.conf 或者 .openerp_serverrc: openerp-serve ...
- 解决li在ie,firefox中行高不一致问题
转载 http://www.cnblogs.com/jikey/archive/2011/11/13/2247543.html li在ie与firefox的高度是不一样的,解决办法是li font-s ...
- 189. Rotate Array -- 将数组前一半移到后一半
Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the array ...
- mvc伪静态<三> IIS配置
上一篇已经已经讲述了mvc伪静态的代码实现. 下面以IIS 7.5为例演示一下IIS如何配置才能在服务器显示.html的伪静态 一.进入IIS,选择处理程序映射 二添加脚本映射 三根据你的处理程序的版 ...