android – 在onScale事件之后触发的奇怪的onScroll事件

我有一个使用SimpleOnScaleGestureListener和SimpleOnGestureListener的应用程序.每当我进行捏缩放时,我得到了预期的onScale,但是当我抬起时,我看到一个奇怪的onScroll,它具有从捏拉变焦开始的起始位置和从捏拉变焦结束的结束位置.我的问题是,我可以防止假滚吗?

这是代码:

@Override
public boolean onTouchEvent(MotionEvent event) {

    // Log every event.
    Log.d(TAG, Here.at() + String.format("Event: %d, Time: %d X: %f, Y: %f", 
            event.getAction(), 
            event.getEventTime(),
            event.getX(),
            event.getY()
            ));

    boolean handled = mScaleDetector.onTouchEvent(event); // This appears to ALWAYS return true (online reference indicated that's what the Android code does).

    handled |= mDetector.onTouchEvent(event);

    handled |= super.onTouchEvent(event);

    return handled;
}

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        // This is required.  If absent, the scale gesture never starts.
        Log.d(TAG, "In onScaleBegin");
        mIgnoreNextDrag = true;
        return true;
    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        Log.d(TAG, "In onScale");
        mTimeScale.doScale(detector.getScaleFactor(), detector.getFocusY());
        invalidate();
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
        Log.d(TAG, "In onScaleEnd");
    }

}

private class GestureListener extends GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onScroll(MotionEvent me1, MotionEvent me2, float distanceX, float distanceY) {

        Log.d(TAG, String.format("Motion Event 1: %d, Time: %d X: %f, Y: %f", 
                me1.getAction(), 
                me1.getEventTime(),
                me1.getX(),
                me1.getY()
                ));

        Log.d(TAG, String.format("Event 2: %d, Time: %d X: %f, Y: %f", 
                me2.getAction(), 
                me2.getEventTime(),
                me2.getX(),
                me2.getY()
                ));


        return true;

    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent me) {
        // Do tap processing.
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        // TODO: Future feature.
        return true;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        // This is required.  If absent, the scroll gesture never starts.
        return true;
    }

}

这是LogCat:

13:06:05.885: D/my-tag(4140): In View.onTouchEvent, Event: 0, Time: 183279420 X: 171.761444, Y: 918.160767
13:06:05.895: D/my-tag(4140): In View.onTouchEvent, Event: 261, Time: 183279420 X: 171.761444, Y: 918.160767
13:06:05.895: D/my-tag(4140): In onScaleBegin
13:06:05.895: I/ScaleGestureDetector(4140): TwScaleGestureDetector
13:06:05.915: D/my-tag(4140): In View.onTouchEvent, Event: 2, Time: 183279458 X: 171.761444, Y: 908.474365
13:06:05.915: D/my-tag(4140): In onScale
13:06:06.015: D/my-tag(4140): In View.onTouchEvent, Event: 2, Time: 183279542 X: 174.964783, Y: 857.584717
13:06:06.015: D/my-tag(4140): In onScale
13:06:06.105: D/my-tag(4140): In View.onTouchEvent, Event: 2, Time: 183279641 X: 232.242096, Y: 731.365662
13:06:06.105: D/my-tag(4140): In onScale
13:06:06.215: D/my-tag(4140): In View.onTouchEvent, Event: 2, Time: 183279740 X: 313.564514, Y: 595.412964
13:06:06.215: D/my-tag(4140): In onScale
13:06:06.225: D/my-tag(4140): In View.onTouchEvent, Event: 6, Time: 183279751 X: 313.564514, Y: 595.412964
13:06:06.225: D/my-tag(4140): In onScaleEnd
13:06:06.245: D/my-tag(4140): In View.onTouchEvent, Event: 2, Time: 183279774 X: 333.316528, Y: 487.607422
13:06:06.245: D/my-tag(4140): In onScroll, me1: 0, Time: 183279420 X: 171.761444, Y: 918.160767
13:06:06.245: D/my-tag(4140): In onScroll, me2 2: 2, Time: 183279774 X: 333.316528, Y: 487.607422
13:06:06.255: D/my-tag(4140): In View.onTouchEvent, Event: 2, Time: 183279784 X: 331.539551, Y: 488.496460
13:06:06.265: D/my-tag(4140): In onScroll, me1: 0, Time: 183279420 X: 171.761444, Y: 918.160767
13:06:06.265: D/my-tag(4140): In onScroll, me2 2: 2, Time: 183279784 X: 331.539551, Y: 488.496460
13:06:06.275: D/my-tag(4140): In View.onTouchEvent, Event: 1, Time: 183279794 X: 331.539551, Y: 488.496460

您可以看到第一个事件是第一个手指向下(0 = ACTION_DOWN),然后第二个手指向下(261 = ACTION_POINTER_2_DOWN).然后我们看到来自onScaleBegin调用的日志条目和来自缩放手势检测器本身的日志(不是来自我的代码).在这一点上,我想我可以放心地假设比例手势已经开始.这完全符合预期.

接下来是四个移动事件(2 = ACTION_MOVE),每个事件后面紧跟着onScale的日志条目.这仍然是预期的.

然后我们看到一个指针向上事件(6 = ACTION_POINTER_UP),然后是来自onScaleEnd的日志条目,仍然是AOK! (注意它是6而不是262因为我按照我放下它的顺序抬起我的手指,所以指针1先被抬起,而不是指针2.)

现在奇怪的一点.

我们看到一个移动事件,它被SimpleOnGestureListener中的onScroll拾取.第一个参数me1具有从缩放手势开始之前的第一个向下事件开始的x和y坐标.第二个参数me2具有在缩放手势停止后显然反映位置的坐标.

在这个例子中,实际上第二个移动事件也被解释为滚动手势,再次使用预缩放原点.使用上面的代码,我会在缩放缩放后不同地获得1,2或无滚动事件.

(为了完成LogCat,我们为第二个手指做了最后一个事件(1 = ACTION_UP),日志变得安静.)

我做错了吗?如果SimpleOnScaleGestureListener从isInProgress返回false,我只尝试调用SimpleOnGestureListener,但没有快乐.

有任何想法吗?

在此先感谢您,感谢社区中所有人,感谢我多年来从这个网站获得的大量信息!

解决方法:

我还发现这种特殊的行为构建了具有平移/缩放功能的自定义视图.但经过一番思考,这是我的理由:

在多点触控环境中,每个手指都被注册,并且在某种并行分析中处理它们各自的运动.这允许检测系统可以通过OnGestureListener和OnScaleGestureListener发送的不同触摸事件.

没错,你还不知道.

现在,想想两个探测器的不同行为:

> GestureDetector通过在视图的可视区域范围内只有一根手指的拖动来检测滚动事件.它的模式响应:向下 – 向上拖动.检测到拖动事件时会生成滚动事件.
> ScaleGestureDetector通过两个手指在多点触控环境中发出的两个同时拖动来检测比例事件.它的模式响应:(down1& down2) – (drag1和/或drag2) – (up1或up2).

现在,考虑一个自定义视图,您只需要检测滚动事件(忽略所有其他事件).在这种情况下,滚动事件必须抛开所有其他注意事项,因为您已执行其模式(向下拖动).

当您将这两个探测器组合在一起时,它们会独立运行,因此刻度探测器首先会发射,但是当您抬起第二根手指时,涡旋探测器会发射,因为它会检测到一个手指拖动并完成一个向上的事件!

结论:行为似乎是合理的……但Android可以为同时情况提供一些交叉检测器.

好吧,你可以简单地放一个布尔值来解决问题.我在实现中完成了这个:

>声明一个名为scaling的布尔值
>创建onDown事件(在ACTION_DOWN事件上)以清除缩放
>制作onScale事件以设置缩放比例
>如果缩放标志为true,则使onScroll事件不处理滚动

这对我来说已经有用了.

上一篇:android – ListView OnScrollListener不会在ViewPager中调用


下一篇:js 事件