onScale事件之后奇怪onScroll事件触发 [英] Weird onScroll event triggered after onScale event

查看:1212
本文介绍了onScale事件之后奇怪onScroll事件触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用SimpleOnScaleGestureListener和SimpleOnGestureListener在一起的应用程序。每当我做了双指缩放我得到预期的onScale的,但是当我抬离我看到一个奇怪的onScroll已经从双指缩放的开始,从双指缩放月底结束位置的起始位置。我的问题是,我可以prevent伪造onScroll?

I have an app that uses a SimpleOnScaleGestureListener and a SimpleOnGestureListener together. Whenever I do a pinch zoom I get the expected onScale's, but when I lift off I see a weird onScroll that has a start position from the beginning of the pinch zoom and an end position from the end of the pinch zoom. My question is, can I prevent the bogus onScroll?

这里的code:

@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中:

Here's the 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电话条目,然后从规模手势探测器本身日志(而不是从我的code)。在这一点上,我想我可以放心地假设规模的姿态已经启动。这是完全按预期。

You can see that the first event is the first finger down (0 = ACTION_DOWN), then the second finger down (261 = ACTION_POINTER_2_DOWN). Then we see log entry from the onScaleBegin call and a log from the scale gesture detector itself (not from my code). At this point I think I can safely assume the scale gesture has been started. This is exactly as expected.

此之后是由四个移动事​​件(2 = ACTION_MOVE),其中的每一个紧接着从onScale日志条目。这仍然是符合市场预期。

This is followed by four move events (2 = ACTION_MOVE), each of which is immediately followed by the log entry from onScale. This is still as expected.

然后,我们看到一个指针向上事件(6 = ACTION_POINTER_UP),其次是来自onScaleEnd,仍然AOK日志条目! (请注意,这是一个6,而不是262,因为我抬起手指以同样的顺序,我把它们记录下来,所以指针1被解除第一,没有指针2。)

Then we see a pointer up event (6 = ACTION_POINTER_UP) followed by the log entry from onScaleEnd, still AOK! (Note that it's a 6 and not a 262 because I lifted my fingers in the same order that I put them down, so pointer 1 was lifted first, not pointer 2.)

现在的怪异位。

我们看到了移动事件,其中被拾起onScroll在SimpleOnGestureListener。第一个参数ME1具有x和从最初的关闭事件y坐标前规模的姿态开始第二个参数ME2具有坐标,显然反映了一个位置,规模的手势停止了之后。

We see a move event, which gets picked up by onScroll in the SimpleOnGestureListener. The first parameter me1 has the x and y coordinates from the very first down event before the scale gesture started The second parameter me2 has coordinates that apparently reflect a position after the scale gesture had stopped.

在这个例子中实际上有一个第二招事件也得到PTED为滚动手势跨$ P $,再以pre-规模原点。有了上面code我会多方面得到捏缩放后的1,2或没有滚动的事件。

In this example there's actually a second move event that also gets interpreted as a scroll gesture, again with the pre-scale origin point. With the above code I would variously get 1, 2 or no scroll events after pinch zooms.

(要为第二个手指玩完LogCat中,我们最后的up事件(1 = ACTION_UP)和日志安静下来。)

(To finish off the LogCat, we a final up event (1 = ACTION_UP) for the second finger and the log goes quiet.)

所以,我做错了?我试着只调用SimpleOnGestureListener如果SimpleOnScaleGestureListener从isInProgress返回false,但没有喜悦。

So am I doing it wrong? I've tried only calling the SimpleOnGestureListener if the SimpleOnScaleGestureListener returns false from isInProgress, but no joy.

任何想法?

在此先感谢,并感谢所有你们都在社区的信息,我从这个网站,多年来得到了大量!

Thanks in advance, and thanks to all y'all in the community for the vast amount of information I've gotten from this site over the years!

推荐答案

我也发现了这种奇特的行为,建设有平移/缩放功能的自定义视图。但是,经过一番思考,这里是我的推理:

I also found this peculiar behaviour building a custom view with pan/zoom capabilities. But after some thought, here is my reasoning:

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

In a multitouch environment, each finger is registered and their respective motions are processed in some kind of parallel analysis. This is what allows the detection of the different touch events the system can send by means of the OnGestureListener and OnScaleGestureListener.

右键,没有什么是你不知道的。

Right, nothing you don't already know.

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

Now, think the different behaviour of the two detectors:

  • GestureDetector 检测到的滚动的事件由拖动的方式只用一根手指里面的视图的可视区域的限制。其模式回应:向下 - 拖 - 向上。滚动的事件是在生产检测拖动事件。

  • GestureDetector detects an scroll event by means of a drag with only one finger inside the limits of the viewable area of the view. Its pattern responds to: down - drag - up. Scroll events are produced as the drag events are detected.

ScaleGestureDetector 检测的比例的由两个同步拖动装置通过两个手指的多点触控的环境激发的事件。其模式响应:(down1&安培; down2) - (drag1和/或drag2) - (UP1 UP2)

ScaleGestureDetector detects scale events by means of two simultaneous drags fired by two fingers in a multitouch environment. Its pattern responds to: (down1&down2) - (drag1 and/or drag2) - (up1 or up2).

而现在,想自定义视图,你只需要检测滚动事件(忽略所有的除外)。在这种情况下,滚动事件必须搁置解雇了,因为你已经完成它的模式的所有其他方面的考虑(下拖了)。

And now, think of a custom view where you only need to detect scroll events (ignoring all the other). In such a case, the scroll event must be fired aside all other considerations because you have performed its pattern (down-drag-up).

当你把这个两个探测器,他们独立行事,所以规模探测器火灾第一,但是当你抬起第二根手指,滚动探测器火灾,因为它检测到的一个手指是的的和向上事件完成!

When you combine this two detectors, they act independently, so the scale detector fires first, but when you lift the second finger, the scroll detector fires because it detects one finger that is dragging and finishing with an up event!

结论:行为似乎合理...但将Android提供了一些交叉点检测的同时进行的情况

Conclusion: The behaviour seems reasonable... yet Android could have provided some cross detector for the simultaneous situation.

好了,你可以简单地把一个布尔值,并解决问题。我曾在我的工作环境下:

Well, you can simply put a boolean and solve the problem. I had this done in my implementation:

  • 声明一个布尔扩展
  • 请您onDown事件(在 ACTION_DOWN 事件)来清除扩展
  • 请您onScale事件来设置扩展
  • 请您onScroll事件不处理滚动,如果扩展标志
  • Declare a boolean named scaling
  • Make your onDown event (on the ACTION_DOWN event) to clear scaling
  • Make your onScale event to set scaling
  • Make your onScroll event not to process the scroll if the scaling flag is true

这为我工作了。

这篇关于onScale事件之后奇怪onScroll事件触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆