[android] ensure that move detector is enabled if double-tap is interrupted
This commit is contained in:
committed by
Łukasz Paczos
parent
11cd2220a1
commit
ac0431eac5
@@ -86,6 +86,8 @@ final class MapGestureDetector {
|
||||
@NonNull
|
||||
private Handler animationsTimeoutHandler = new Handler();
|
||||
|
||||
private boolean doubleTapRegistered;
|
||||
|
||||
MapGestureDetector(@Nullable Context context, Transform transform, Projection projection, UiSettings uiSettings,
|
||||
AnnotationManager annotationManager, CameraChangeDispatcher cameraChangeDispatcher) {
|
||||
this.annotationManager = annotationManager;
|
||||
@@ -199,7 +201,12 @@ final class MapGestureDetector {
|
||||
boolean result = gesturesManager.onTouchEvent(motionEvent);
|
||||
|
||||
switch (motionEvent.getActionMasked()) {
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
doubleTapFinished();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
doubleTapFinished();
|
||||
transform.setGestureInProgress(false);
|
||||
|
||||
if (!scheduledAnimators.isEmpty()) {
|
||||
@@ -215,6 +222,7 @@ final class MapGestureDetector {
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
scheduledAnimators.clear();
|
||||
transform.setGestureInProgress(false);
|
||||
doubleTapFinished();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -344,16 +352,10 @@ final class MapGestureDetector {
|
||||
int action = motionEvent.getActionMasked();
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
doubleTapFocalPoint = new PointF(motionEvent.getX(), motionEvent.getY());
|
||||
|
||||
// disable the move detector in preparation for the quickzoom,
|
||||
// so that we don't move the map's center slightly before the quickzoom is started (see #14227)
|
||||
gesturesManager.getMoveGestureDetector().setEnabled(false);
|
||||
doubleTapStarted();
|
||||
}
|
||||
|
||||
if (motionEvent.getActionMasked() == MotionEvent.ACTION_UP) {
|
||||
// re-enable the move detector
|
||||
gesturesManager.getMoveGestureDetector().setEnabled(true);
|
||||
|
||||
float diffX = Math.abs(motionEvent.getX() - doubleTapFocalPoint.x);
|
||||
float diffY = Math.abs(motionEvent.getY() - doubleTapFocalPoint.y);
|
||||
if (diffX > doubleTapMovementThreshold || diffY > doubleTapMovementThreshold) {
|
||||
@@ -426,6 +428,21 @@ final class MapGestureDetector {
|
||||
}
|
||||
}
|
||||
|
||||
private void doubleTapStarted() {
|
||||
// disable the move detector in preparation for the quickzoom,
|
||||
// so that we don't move the map's center slightly before the quickzoom is started (see #14227)
|
||||
gesturesManager.getMoveGestureDetector().setEnabled(false);
|
||||
doubleTapRegistered = true;
|
||||
}
|
||||
|
||||
private void doubleTapFinished() {
|
||||
if (doubleTapRegistered) {
|
||||
// re-enable the move detector in case of double tap
|
||||
gesturesManager.getMoveGestureDetector().setEnabled(true);
|
||||
doubleTapRegistered = false;
|
||||
}
|
||||
}
|
||||
|
||||
private final class MoveGestureListener extends MoveGestureDetector.SimpleOnMoveGestureListener {
|
||||
@Override
|
||||
public boolean onMoveBegin(@NonNull MoveGestureDetector detector) {
|
||||
@@ -481,6 +498,8 @@ final class MapGestureDetector {
|
||||
if (!uiSettings.isQuickZoomGesturesEnabled()) {
|
||||
return false;
|
||||
}
|
||||
// re-try disabling the move detector in case double tap has been interrupted before quickzoom started
|
||||
gesturesManager.getMoveGestureDetector().setEnabled(false);
|
||||
}
|
||||
|
||||
cancelTransitionsIfRequired();
|
||||
@@ -516,9 +535,7 @@ final class MapGestureDetector {
|
||||
@Override
|
||||
public void onScaleEnd(@NonNull StandardScaleGestureDetector detector, float velocityX, float velocityY) {
|
||||
if (quickZoom) {
|
||||
// re-enabled the move detector only if the quickzoom happened
|
||||
// we need to split the responsibility of re-enabling the move detector,
|
||||
// because the double tap event (where the detector is disabled) can be canceled without warning (see #14598)
|
||||
// re-enabled the move detector if the quickzoom happened
|
||||
gesturesManager.getMoveGestureDetector().setEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -158,4 +158,29 @@ class MapGestureDetectorTest : BaseTest() {
|
||||
Assert.assertEquals(initialZoom!!, mapboxMap.cameraPosition.zoom, 0.01)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleTap_interrupted_moveStillEnabled() {
|
||||
validateTestSetup()
|
||||
|
||||
rule.runOnUiThread {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
|
||||
}
|
||||
|
||||
onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold / 2, withVelocity = false, duration = 50L, interrupt = true))
|
||||
|
||||
var expectedTarget: LatLng? = null
|
||||
rule.runOnUiThread {
|
||||
val currentPoint = mapboxMap.projection.toScreenLocation(mapboxMap.cameraPosition.target)
|
||||
val resultingPoint = PointF(currentPoint.x + maxWidth / 2f, currentPoint.y + maxHeight / 2f)
|
||||
expectedTarget = mapboxMap.projection.fromScreenLocation(resultingPoint)
|
||||
}
|
||||
|
||||
// move to expected target
|
||||
onView(withId(R.id.mapView)).perform(move(-maxWidth / 2f, -maxHeight / 2f, withVelocity = false))
|
||||
rule.runOnUiThread {
|
||||
Assert.assertEquals(expectedTarget!!.latitude, mapboxMap.cameraPosition.target.latitude, 10.0)
|
||||
Assert.assertEquals(expectedTarget!!.longitude, mapboxMap.cameraPosition.target.longitude, 10.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user