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

时间:2013-07-26 20:32:52

标签: android gestures 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,但没有快乐。

有什么想法吗?

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

1 个答案:

答案 0 :(得分:6)

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

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

是的,没有你不知道的。

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

  • GestureDetector通过在视图的可视区域范围内只有一根手指的拖动来检测滚动事件。它的模式响应:向下 - 向上拖动。检测到拖动事件时会生成滚动事件。

  • ScaleGestureDetector通过两个手指在多点触控环境中触发的两个同时拖动来检测比例事件。它的模式响应:( down1& down2) - (drag1和/或drag2) - (up1 up2)。

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

当你将这两个探测器组合在一起时,它们会独立行动,因此刻度探测器首先会发射,但当你抬起第二根手指时,滚动探测器会发射,因为它会检测一个手指拖动并完成一个up事件!

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

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

  • 声明名为boolean
  • scaling
  • 制作onDown活动(在ACTION_DOWN活动上)以清除scaling
  • 设置onScale事件以设置scaling
  • 如果scaling标记为true
  • ,则使您的onScroll事件不处理滚动

这对我来说已经有用了。