Mam aplikację, która używa razem SimpleOnScaleGestureListener i SimpleOnGestureListener. Za każdym razem, gdy robię zoom zbliżenia, uzyskuję oczekiwany efekt onScale, ale kiedy się podniosę, widzę dziwny onScroll, który ma pozycję początkową od początku powiększenia szczypcami i pozycję końcową od końca powiększenia szczypta. Moje pytanie brzmi: czy mogę zapobiec fałszywemu inSroll?Dziwne zdarzenie onScroll wyzwalane po zdarzeniu onScale
Oto kod:
@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;
}
}
oto 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
Widać, że pierwsze zdarzenie to pierwszy palec w dół (0 = ACTION_DOWN), następnie drugi palec w dół (261 = ACTION_POINTER_2_DOWN). Następnie widzimy wpis w dzienniku z wywołania onScaleBegin i log z detektora gestów skalowania (nie z mojego kodu). W tym momencie myślę, że mogę bezpiecznie założyć, że gest skali już się rozpoczął. Dokładnie zgodnie z oczekiwaniami.
Po nim następują cztery ruchy (2 = ACTION_MOVE), po których następuje natychmiast wpis dziennika z onScale. Jest to wciąż zgodne z oczekiwaniami.
Następnie widzimy wskaźnik w górę zdarzenia (6 = ACTION_POINTER_UP), a następnie wpis w dzienniku z onScaleEnd, nadal AOK! (Zauważ, że to 6, a nie 262, ponieważ podniosłem palce w takiej samej kolejności, w jakiej je odkładałem, więc wskaźnik 1 został podniesiony pierwszy, a nie wskaźnik 2.)
Teraz dziwny kawałek.
Widzimy zdarzenie przenoszenia, które zostanie pobrane przez onScroll w SimpleOnGestureListener. Pierwszy parametr me1 ma współrzędne xiy od pierwszego zderzenia przed wywołaniem gestu skalowania Drugi parametr me2 ma współrzędne, które najwyraźniej odzwierciedlają położenie po zatrzymaniu gestu skali.
W tym przykładzie występuje zdarzenie drugiego ruchu, które również interpretowane jest jako gest przewijania, ponownie z punktem początkowym skali wstępnej. Dzięki powyższemu kodowi różnie dostałbym 1, 2 lub brak zdarzeń przewijania po zbliżeniu z szczyptą.
(do wykończenia logcat, że ostateczna się impreza (1 = ACTION_UP) dla drugiego palca i dziennik idzie cicho.)
Więc robię to źle? Próbowałem tylko wywoływanie SimpleOnGestureListener, jeśli SimpleOnScaleGestureListener zwraca false z isInProgress, ale bez radości.
Wszelkie pomysły?
Z góry dziękuję i dziękuję wszystkim w społeczności za ogromną ilość informacji, które otrzymałem z tej strony przez lata!
Dobry plan, a dzięki za szczegółową odpowiedź. Wprowadziłem teraz coś bardzo podobnego, co pomaga mi zignorować zwój. –