我正在使用SimpleOnGestureListener来检测onSingleTapUp事件和视图。

该视图的比例因子为5,因此1个屏幕像素对应于我视图中的5个像素:

  view.setScaleX(5);
  view.setScaleY(5);

我面临的问题是没有正确检测到Tap事件。我查看了SimpleOnGestureListener的源代码,相关部分是:
  • Here如果触摸点未超过某个阈值,则会调用SingleTapUp()侦听器
  • Here
    触摸点的行进距离计算为

  • 我认为未可靠检测到Tap的原因是,触摸点的距离计算依赖于视图的缩放局部坐标(e.getX()e.getY()),而不是原始坐标(e.getRawX()e.getRawY())。

    由于比例因子,手指在屏幕上的微小移动会导致e.getX()e.getY()发生较大变化。

    我对代码的解释正确吗?如果是这样,我该如何解决此问题?

    现在,我的解决方法是拦截没有比例因子的View上的所有事件,然后自己将MotionEvents调度到具有比例因子的视图中。

    它运作良好,但我仍然对我对android代码的分析是否正确感兴趣。

    我正在使用android 4.4

    最佳答案

    恕我直言,您对代码的分析是正确的!
    在探索源代码时发现了一些附加信息:

  • 在变量 mTouchSlopSquare 中定义的距离和已初始化的here(存储为原始值的平方,仅用于优化)
  • 如果您将Context传递给GestureDetector的构造函数(应该是,因为第二个已经过时了),则此值将根据this line
  • 等于com.android.internal.R.dimen.config_viewConfigurationTouchSlop
  • 比较是在this line中完成的同一区域内的触摸

  • 解决方法
    作为解决方法,我建议您访问mTouchSlopSquare的私有成员GestureDetector并在此距离计算中添加比例因子。
    请参阅下面的代码:
    // 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);
    
    我检查了一下,它对我有用。

    10-04 17:51