GestureDetector.SimpleOnGestureListener 不尊重视图比例因子?
GestureDetector.SimpleOnGestureListener not respecting View scale factor?
我正在使用 SimpleOnGestureListener to detect the onSingleTapUp 事件和视图。
视图的比例因子为 5,因此 1 个屏幕像素对应于我视图中的 5 个像素:
view.setScaleX(5);
view.setScaleY(5);
我面临的问题是没有准确检测到 Tap 事件。我查看了SimpleOnGestureListener
的源代码,相关部分是:
我认为不能可靠地检测到 Tap 的原因是触摸点的距离计算依赖于视图的缩放局部坐标(e.getX()
和 e.getY()
)而不是原始坐标(e.getRawX()
和 e.getRawY()
)。
由于比例因子,手指在屏幕上的微小移动将导致 e.getX()
和 e.getY()
的较大变化。
我对代码的解释是否正确?如果是这样,我该如何解决这个问题?
目前我的解决方法是拦截 View
上没有比例因子的所有事件,然后自己将 MotionEvents
调度到具有比例因子的视图。
它运行良好,我仍然对我对 android 代码的分析是否正确感兴趣。
我正在使用 android 4.4
恕我直言,您对代码的分析是正确的!
只是在探索源代码时发现的一些附加信息:
- 变量
mTouchSlopSquare
and initialized here中定义的距离(存储为原始值的平方,仅用于优化)
- 如果您将 Context 传递给
GestureDetector
的构造函数(应该是,因为第二个构造函数已过时),那么根据 this line[=37=,此值等于 com.android.internal.R.dimen.config_viewConfigurationTouchSlop
]
- 比较是在 this line
中完成的同一区域触摸
解决方法
作为解决方法,我建议您访问 GestureDetector
的私人成员 mTouchSlopSquare
并在此距离计算中添加比例因子。
查看下面我的代码:
// Utility method
public static boolean fixGestureDetectorScale(GestureDetector detector, float scale) {
try {
Field f = GestureDetector.class.getDeclaredField("mTouchSlopSquare");
f.setAccessible(true);
int touchSlopSquare = (int) f.get(detector);
float touchSlop = (float) Math.sqrt(touchSlopSquare);
//normalize touchSlop
touchSlop /= scale;
touchSlopSquare = Math.round(touchSlop * touchSlop);
f.set(detector, touchSlopSquare);
} catch (NoSuchFieldException e) {
e.printStackTrace();
return false;
} catch (IllegalAccessException e) {
e.printStackTrace();
return false;
}
return true;
}
// usage
fixGestureDetectorScale(mGestureDetector, scale);
view.setScaleX(scale);
view.setScaleY(scale);
我已经检查过了,它适合我。
我正在使用 SimpleOnGestureListener to detect the onSingleTapUp 事件和视图。
视图的比例因子为 5,因此 1 个屏幕像素对应于我视图中的 5 个像素:
view.setScaleX(5);
view.setScaleY(5);
我面临的问题是没有准确检测到 Tap 事件。我查看了SimpleOnGestureListener
的源代码,相关部分是:
我认为不能可靠地检测到 Tap 的原因是触摸点的距离计算依赖于视图的缩放局部坐标(e.getX()
和 e.getY()
)而不是原始坐标(e.getRawX()
和 e.getRawY()
)。
由于比例因子,手指在屏幕上的微小移动将导致 e.getX()
和 e.getY()
的较大变化。
我对代码的解释是否正确?如果是这样,我该如何解决这个问题?
目前我的解决方法是拦截 View
上没有比例因子的所有事件,然后自己将 MotionEvents
调度到具有比例因子的视图。
它运行良好,我仍然对我对 android 代码的分析是否正确感兴趣。
我正在使用 android 4.4
恕我直言,您对代码的分析是正确的!
只是在探索源代码时发现的一些附加信息:
- 变量
mTouchSlopSquare
and initialized here中定义的距离(存储为原始值的平方,仅用于优化) - 如果您将 Context 传递给
GestureDetector
的构造函数(应该是,因为第二个构造函数已过时),那么根据 this line[=37=,此值等于com.android.internal.R.dimen.config_viewConfigurationTouchSlop
] - 比较是在 this line 中完成的同一区域触摸
解决方法
作为解决方法,我建议您访问 GestureDetector
的私人成员 mTouchSlopSquare
并在此距离计算中添加比例因子。
查看下面我的代码:
// Utility method
public static boolean fixGestureDetectorScale(GestureDetector detector, float scale) {
try {
Field f = GestureDetector.class.getDeclaredField("mTouchSlopSquare");
f.setAccessible(true);
int touchSlopSquare = (int) f.get(detector);
float touchSlop = (float) Math.sqrt(touchSlopSquare);
//normalize touchSlop
touchSlop /= scale;
touchSlopSquare = Math.round(touchSlop * touchSlop);
f.set(detector, touchSlopSquare);
} catch (NoSuchFieldException e) {
e.printStackTrace();
return false;
} catch (IllegalAccessException e) {
e.printStackTrace();
return false;
}
return true;
}
// usage
fixGestureDetectorScale(mGestureDetector, scale);
view.setScaleX(scale);
view.setScaleY(scale);
我已经检查过了,它适合我。