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);

我已经检查过了,它适合我。