使用GestureDetector onScroll时出现滚动延迟

8
我使用GestureDetector在自定义View中实现滚动。 我的实现基于这个链接: Smooth scrolling with inertia and edge resistance/snapback

我注意到在滚动开始之前会有一个短暂的暂停: 我检查了onScroll消息,并注意到只有在手指移动很远时,第一个消息才会到达,这会导致滚动开始时明显的延迟。 之后滚动就很流畅了。
看起来GestureDetector开始发送onScroll消息只有在motionevents之间有最小距离时,以确保手势不是长按或轻触(btw我设置了setIsLongpressEnabled(false))。
有没有办法改变这种行为并创建一个平滑的滚动,而不是使用低级别的touch事件实现自定义滚动手势?
2个回答

11
答案是否定的,你必须创建自己的GestureDetector。如果你查看Android源代码(GestureDetector.java),524到540行用于检测单击的“触摸距离”。具体来说,第528行防止调用onScroll事件,直到移动超出了触摸距离(这是从视图配置中拉出的)。你无法更改视图配置,并且这个距离被硬编码为16像素。这是导致你看到延迟的半径。

1
或者你可以在构造函数之后使用反射设置mTouchSlopSquare(仅在您关心onScroll而不关心其他内容时才这样做)。`private fun GestureDetector.hackTouchSlop() { try { val touchSlopField = javaClass.getDeclaredField("mTouchSlopSquare") touchSlopField.isAccessible = true touchSlopField.set(this, 0) } catch (ignored: Throwable) { } }` - Mate Herber

0

你可以使用反射来改变mTouchSlopSquare,源自GestureDetector.java

    public static void setGestureDetectorTouchSlop(GestureDetector gestureDetector, int value) {
        try {
            Field f_mTouchSlopSquare = GestureDetector.class.getDeclaredField("mTouchSlopSquare");
            f_mTouchSlopSquare.setAccessible(true);
            f_mTouchSlopSquare.setInt(gestureDetector, value * value);
        } catch (NoSuchFieldException | IllegalAccessException | NullPointerException e) {
            Log.w(TAG, gestureDetector.toString(), e);
        }
    }

另外,这里是更改 GestureDetectorCompat.java slop 的方法。

    public static void setGestureDetectorTouchSlop(GestureDetectorCompat gestureDetector, int value) {
        try {
            Field f_mImpl = GestureDetectorCompat.class.getDeclaredField("mImpl");
            f_mImpl.setAccessible(true);
            Object mImpl = f_mImpl.get(gestureDetector);
            if (mImpl == null) {
                Log.w(TAG, f_mImpl + " is null");
                return;
            }
            Class<?> c_GDCIJellybeanMr2 = null;
            Class<?> c_GDCIBase = null;
            try {
                c_GDCIJellybeanMr2 = Class.forName(GestureDetectorCompat.class.getName() + "$GestureDetectorCompatImplJellybeanMr2");
                c_GDCIBase = Class.forName(GestureDetectorCompat.class.getName() + "$GestureDetectorCompatImplBase");
            } catch (ClassNotFoundException ignored) {
            }
            if (c_GDCIJellybeanMr2 != null && c_GDCIJellybeanMr2.isInstance(mImpl)) {
                Field f_mDetector = c_GDCIJellybeanMr2.getDeclaredField("mDetector");
                f_mDetector.setAccessible(true);

                Object mDetector = f_mDetector.get(mImpl);
                if (mDetector instanceof GestureDetector)
                    setGestureDetectorTouchSlop((GestureDetector) mDetector, value);
            } else if (c_GDCIBase != null) {
                Field f_mTouchSlopSquare = c_GDCIBase.getDeclaredField("mTouchSlopSquare");
                f_mTouchSlopSquare.setAccessible(true);
                f_mTouchSlopSquare.setInt(mImpl, value * value);
            } else {
                Log.w(TAG, "not handled: " + mImpl.getClass().toString());
            }
        } catch (NoSuchFieldException | IllegalAccessException | NullPointerException e) {
            Log.w(TAG, gestureDetector.getClass().toString(), e);
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接